[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