[asterisk-commits] sruffell: branch sruffell/asterisk-1.4-transcoder r148422 - /team/sruffell/as...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Oct 10 17:49:03 CDT 2008


Author: sruffell
Date: Fri Oct 10 17:49:02 2008
New Revision: 148422

URL: http://svn.digium.com/view/asterisk?view=rev&rev=148422
Log:
Adding support for translation to and from signed linear directly in
codec_dahdi.

Issue: DAHDI-193

Modified:
    team/sruffell/asterisk-1.4-transcoder/codecs/codec_dahdi.c

Modified: team/sruffell/asterisk-1.4-transcoder/codecs/codec_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/sruffell/asterisk-1.4-transcoder/codecs/codec_dahdi.c?view=diff&rev=148422&r1=148421&r2=148422
==============================================================================
--- team/sruffell/asterisk-1.4-transcoder/codecs/codec_dahdi.c (original)
+++ team/sruffell/asterisk-1.4-transcoder/codecs/codec_dahdi.c Fri Oct 10 17:49:02 2008
@@ -56,6 +56,8 @@
 #include "asterisk/utils.h"
 #include "asterisk/linkedlists.h"
 #include "asterisk/dahdi_compat.h"
+#include "asterisk/frame.h"
+#include "asterisk/ulaw.h"
 
 #define BUFFER_SAMPLES	8000
 
@@ -110,7 +112,40 @@
 	int fake;
 	int samples;
 	struct dahdi_transcoder_formats fmts;
+	enum {NONE=0, SLINTOULAW, ULAWTOSLIN} soft_slin;
+	uint8_t ulaw_buffer[160];
 };
+
+static int ulawtolin(struct ast_trans_pvt *pvt)
+{
+	struct pvt *ztp = pvt->pvt;
+	int i = ztp->samples;
+	uint8_t *src = &ztp->ulaw_buffer[0];
+	int16_t *dst = (int16_t *)pvt->outbuf + pvt->datalen;
+
+	/* convert and copy in outbuf */
+	while (i--)
+		*dst++ = AST_MULAW(*src++);
+
+	return 0;
+}
+
+static int lintoulaw(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct pvt *ztp = pvt->pvt;
+	int i = f->samples;
+	uint8_t *dst = &ztp->ulaw_buffer[0];
+	int16_t *src = (int16_t*)f->data;
+
+	if (i > sizeof(ztp->ulaw_buffer)) {
+		ast_log(LOG_ERROR, "Cannot convert more that %d samples.\n", ztp->samples);
+		return 0;
+	}
+	while (i--)
+		*dst++ = AST_LIN2MU(*src++);
+
+	return 0;
+}
 
 static int transcoder_show(int fd, int argc, char **argv)
 {
@@ -132,12 +167,22 @@
 	struct pvt *ztp = pvt->pvt;
 
 	if (f->subclass) {
-		/* Give the frame to the hardware transcoder... */
-		res = write(ztp->fd, f->data, f->datalen); 
+		int write_size;
+		/* If we received a frame in signed linear format, and the
+		 * hardware doesn't support signed linear format, we need to
+		 * convert it before sending it to the hardware. */
+		if (SLINTOULAW == ztp->soft_slin) {
+			lintoulaw(pvt, f);
+			write_size = sizeof(ztp->ulaw_buffer);
+			res = write(ztp->fd, ztp->ulaw_buffer, sizeof(ztp->ulaw_buffer)); 
+		} else {
+			write_size = f->datalen;
+			res = write(ztp->fd, f->data, f->datalen); 
+		}
 		if (-1 == res) {
 			ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno));
 		}
-		if (f->datalen != res) {
+		if (write_size != res) {
 			ast_log(LOG_ERROR, "Requested write of %d bytes, but only wrote %d bytes.\n", f->datalen, res);
 		}
 		res = -1;
@@ -158,7 +203,11 @@
 	if (0 == ztp->fake) {
 		int res;
 		/* Let's check to see if there is a new frame for us.... */
-		res = read(ztp->fd, pvt->outbuf + pvt->datalen, pvt->t->buf_size - pvt->datalen);
+		if (ULAWTOSLIN == ztp->soft_slin) {
+			res = read(ztp->fd, ztp->ulaw_buffer, sizeof(ztp->ulaw_buffer));
+		} else {
+			res = read(ztp->fd, pvt->outbuf + pvt->datalen, pvt->t->buf_size - pvt->datalen);
+		}
 		if (-1 == res) {
 			if (EWOULDBLOCK == errno) {
 				/* Nothing waiting... */
@@ -168,8 +217,13 @@
 				return NULL;
 			}
 		} else {
+			if (ULAWTOSLIN == ztp->soft_slin) {
+				ulawtolin(pvt);
+				pvt->f.datalen = res * 2;
+			} else {
+				pvt->f.datalen = res;
+			}
 			pvt->f.samples = ztp->samples;
-			pvt->f.datalen = res;
 			pvt->datalen = 0;
 			pvt->f.frametype = AST_FRAME_VOICE;
 			pvt->f.subclass = 1 <<  (pvt->t->dstfmt);
@@ -229,6 +283,7 @@
 	int fd;
 	struct pvt *ztp = pvt->pvt;
 	int flags;
+	int tried_once = 0;
 	
 #ifdef HAVE_ZAPTEL
 	if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) {
@@ -245,14 +300,36 @@
 	ztp->fmts.srcfmt = (1 << source);
 	ztp->fmts.dstfmt = (1 << dest);
 
-	ast_log(LOG_VERBOSE, "Opening transcoder channel from %d to %d.\n", source, dest);
-
+	ast_log(LOG_DEBUG, "Opening transcoder channel from %d to %d.\n", source, dest);
+
+retry:
 	if (ioctl(fd, DAHDI_TC_ALLOCATE, &ztp->fmts)) {
+		if ((ENODEV == errno) && !tried_once) {
+			/* We requested to translate to/from an unsupported
+			 * format.  Most likely this is because signed linear
+			 * was not supported by any hardware devices even
+			 * though this module always registers signed linear
+			 * support. In this case we'll retry, requesting
+			 * support for ULAW instead of signed linear and then
+			 * we'll just convert from ulaw to signed linear in
+			 * software. */
+			if (AST_FORMAT_SLINEAR == ztp->fmts.srcfmt) {
+				ast_log(LOG_DEBUG, "Using soft_slin support on source\n");
+				ztp->soft_slin = SLINTOULAW;
+				ztp->fmts.srcfmt = AST_FORMAT_ULAW;
+			} else if (AST_FORMAT_SLINEAR == ztp->fmts.dstfmt) {
+				ast_log(LOG_DEBUG, "Using soft_slin support on destination\n");
+				ztp->soft_slin = ULAWTOSLIN;
+				ztp->fmts.dstfmt = AST_FORMAT_ULAW;
+			}
+			tried_once = 1;
+			goto retry;
+		}
 		ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno));
 		close(fd);
 
 		return -1;
-	}
+	} 
 
 	flags = fcntl(fd, F_GETFL);
 	if (flags > - 1) {
@@ -437,8 +514,21 @@
 	for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) {
 		if (option_verbose > 1)
 			ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name);
+
+		/* Complex codecs need to support signed linear.  If the
+		 * hardware transcoder does not natively support signed linear
+		 * format, we will emulate it in software directly in this
+		 * module. */
+		if (info.dstfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) {
+			info.dstfmts |= AST_FORMAT_SLINEAR;
+		}
+		if (info.srcfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) {
+			info.srcfmts |= AST_FORMAT_SLINEAR;
+		}
+
 		build_translators(&map, info.dstfmts, info.srcfmts);
 		ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2);
+
 	}
 
 	close(fd);
@@ -480,6 +570,7 @@
 
 static int load_module(void)
 {
+	ast_ulaw_init();
 	parse_config();
 	find_transcoders();
 	ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0]));




More information about the asterisk-commits mailing list