[asterisk-commits] murf: branch group/newcdr r176942 - in /team/group/newcdr: ./ apps/ channels/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Feb 18 09:05:42 CST 2009


Author: murf
Date: Wed Feb 18 09:05:41 2009
New Revision: 176942

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=176942
Log:
Merged revisions 176708,176760,176771,176841,176869,176901,176904 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r176708 | jpeeler | 2009-02-17 15:08:00 -0700 (Tue, 17 Feb 2009) | 24 lines

Merged revisions 176701 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r176701 | jpeeler | 2009-02-17 15:54:34 -0600 (Tue, 17 Feb 2009) | 17 lines
  
  Modify bridging to properly evaluate DTMF after first warning is played
  
  The main problem is currently if the Dial flag L is used with a warning sound,
  DTMF is not evaluated after the first warning sound. To fix this, a flag has 
  been added in ast_generic_bridge for playing the warning which ensures that if
  a scheduled warning is missed, multiple warrnings are not played back (due to a
  feature evaluation or waiting for digits). ast_channel_bridge was modified to
  store the nexteventts in the ast_bridge_config structure as that information
  was lost every time ast_channel_bridge was reentered, causing a hangup due to
  incorrect time calculations.
  
  (closes issue #14315)
  Reported by: tim_ringenbach
 
  Reviewed on reviewboard:
  http://reviewboard.digium.com/r/163/
........

................
r176760 | sruffell | 2009-02-17 15:28:41 -0700 (Tue, 17 Feb 2009) | 10 lines

Several changes to codec_dahdi to play nice with G723.

This commit brings in the changes that were living out on the
svn/asterisk/team/sruffell/asterisk-trunk-transcoder branch.  codec_dahdi.c now
always uses signed linear as the simple codec so that a soft g729 codec will
not end up being preferred to the hardware codec.  There are also changes to
allow codec_dahdi.c to feed packets to the hardware in the native sample size of
the codec.  This solves problems with choppy audio when using G723. 


................
r176771 | russell | 2009-02-17 15:52:43 -0700 (Tue, 17 Feb 2009) | 2 lines

Remove a dependency that no longer exists.

................
r176841 | kpfleming | 2009-02-17 19:02:54 -0700 (Tue, 17 Feb 2009) | 3 lines

suppress smoothers for Siren codecs as well as Speex and G.723.1


................
r176869 | dhubbard | 2009-02-17 19:55:12 -0700 (Tue, 17 Feb 2009) | 7 lines

T38 faxdetect should jump to the 'fax' extension for incoming calls only

The previous implementation of T38 faxdetect resulted in both sides of the
call jumping to a fax extension when both sides had 't38pt_udptl=yes' and
'faxdetect=yes' in sip.conf and a 'fax' extension in the current context.
This revision will jump to a 'fax' extension on incoming calls only.

................
r176901 | russell | 2009-02-17 23:00:40 -0700 (Tue, 17 Feb 2009) | 9 lines

Fix a number of incorrect uses of strncpy().

The big problem here is that the 3rd argument provided in these uses of strncpy()
did not reserve a byte for the null terminator, leaving the potential for writing
one byte past the end of the buffer.

Aside from this, there were coding guidelines violations with regards to spacing,
as well as hard coded lengths being used instead of sizeof().

................
r176904 | russell | 2009-02-17 23:14:47 -0700 (Tue, 17 Feb 2009) | 2 lines

Add example code for a heap traversal.

................

Modified:
    team/group/newcdr/   (props changed)
    team/group/newcdr/apps/app_milliwatt.c
    team/group/newcdr/channels/chan_sip.c
    team/group/newcdr/codecs/codec_dahdi.c
    team/group/newcdr/include/asterisk/channel.h
    team/group/newcdr/include/asterisk/heap.h
    team/group/newcdr/main/channel.c
    team/group/newcdr/main/features.c
    team/group/newcdr/main/pbx.c
    team/group/newcdr/main/rtp.c

Propchange: team/group/newcdr/
------------------------------------------------------------------------------
    automerge = yes

Propchange: team/group/newcdr/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/newcdr/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Feb 18 09:05:41 2009
@@ -1,1 +1,1 @@
-/trunk:1-176707
+/trunk:1-176941

Modified: team/group/newcdr/apps/app_milliwatt.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/apps/app_milliwatt.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/apps/app_milliwatt.c (original)
+++ team/group/newcdr/apps/app_milliwatt.c Wed Feb 18 09:05:41 2009
@@ -24,10 +24,6 @@
  * 
  * \ingroup applications
  */
-
-/*** MODULEINFO
-	<depend>res_indications</depend>
- ***/
 
 #include "asterisk.h"
 

Modified: team/group/newcdr/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/channels/chan_sip.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/channels/chan_sip.c (original)
+++ team/group/newcdr/channels/chan_sip.c Wed Feb 18 09:05:41 2009
@@ -4617,8 +4617,8 @@
 	if (message)
 		ast_queue_control_data(chan, AST_CONTROL_T38, &message, sizeof(message));
 
-	if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) {
-		/* fax detection is enabled */
+	if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT) && !p->outgoing_call) {
+		/* fax detection is enabled and this is an incoming call */
 		ast_channel_lock(chan);
 		if (strcmp(chan->exten, "fax") && state == T38_ENABLED) {
 			const char *target_context = S_OR(chan->macrocontext, chan->context);

Modified: team/group/newcdr/codecs/codec_dahdi.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/codecs/codec_dahdi.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/codecs/codec_dahdi.c (original)
+++ team/group/newcdr/codecs/codec_dahdi.c Wed Feb 18 09:05:41 2009
@@ -38,7 +38,7 @@
 #include <netinet/in.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-
+#include <sys/poll.h>
 #include <dahdi/user.h>
 
 #include "asterisk/lock.h"
@@ -49,8 +49,12 @@
 #include "asterisk/channel.h"
 #include "asterisk/utils.h"
 #include "asterisk/linkedlists.h"
-
-#define BUFFER_SAMPLES	8000
+#include "asterisk/ulaw.h"
+
+#define BUFFER_SIZE 8000
+
+#define G723_SAMPLES 240
+#define G729_SAMPLES 160
 
 static unsigned int global_useplc = 0;
 
@@ -79,12 +83,52 @@
 
 static AST_LIST_HEAD_STATIC(translators, translator);
 
-struct pvt {
+struct codec_dahdi_pvt {
 	int fd;
-	int fake;
 	struct dahdi_transcoder_formats fmts;
-	int samples;
+	unsigned int softslin:1;
+	unsigned int fake:2;
+	uint16_t required_samples;
+	uint16_t samples_in_buffer;
+	uint8_t ulaw_buffer[1024];
 };
+
+/* Only used by a decoder */
+static int ulawtolin(struct ast_trans_pvt *pvt)
+{
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+	int i = dahdip->required_samples;
+	uint8_t *src = &dahdip->ulaw_buffer[0];
+	int16_t *dst = pvt->outbuf.i16 + pvt->datalen;
+
+	/* convert and copy in outbuf */
+	while (i--) {
+		*dst++ = AST_MULAW(*src++);
+	}
+
+	return 0;
+}
+
+/* Only used by an encoder. */
+static int lintoulaw(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+	int i = f->samples;
+	uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer];
+	int16_t *src = f->data.ptr;
+
+	if (dahdip->samples_in_buffer + i > sizeof(dahdip->ulaw_buffer)) {
+		ast_log(LOG_ERROR, "Out of buffer space!\n");
+		return -i;
+	}
+
+	while (i--) {
+		*dst++ = AST_LIN2MU(*src++);
+	}
+
+	dahdip->samples_in_buffer += f->samples;
+	return 0;
+}
 
 static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
@@ -114,68 +158,79 @@
 	return CLI_SUCCESS;
 }
 
-static int dahdi_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
 {
 	int res;
-	struct pvt *dahdip = pvt->pvt;
-
-	if (f->subclass) {
-		/* Give the frame to the hardware transcoder... */
-		res = write(dahdip->fd, f->data.ptr, f->datalen); 
+	struct pollfd p = {0};
+	if (!count) return;
+	res = write(dahdip->fd, buffer, count);
+	if (option_verbose > 10) {
 		if (-1 == res) {
-			ast_log(LOG_ERROR, "Failed to write to /dev/dahdi/transcode: %s\n", strerror(errno));
-		}
-		if (f->datalen != res) {
-			ast_log(LOG_ERROR, "Requested write of %d bytes, but only wrote %d bytes.\n", f->datalen, res);
-		}
-		res = -1;
-		pvt->samples += f->samples;
-	} else {
-		/* Fake a return frame for calculation purposes */
+			ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno));
+		}
+		if (count != res) {
+			ast_log(LOG_ERROR, "Requested write of %zd bytes, but only wrote %d bytes.\n", count, res);
+		}
+	}
+	p.fd = dahdip->fd;
+	p.events = POLLOUT;
+	res = poll(&p, 1, 50);
+}
+
+static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+
+	if (!f->subclass) {
+		/* We're just faking a return for calculation purposes. */
 		dahdip->fake = 2;
 		pvt->samples = f->samples;
-		res = 0;
-	}
-	return res;
-}
-
-static struct ast_frame *dahdi_frameout(struct ast_trans_pvt *pvt)
-{
-	struct pvt *dahdip = pvt->pvt;
-
-	if (0 == dahdip->fake) {
-		int res;
-		/* Let's check to see if there is a new frame for us.... */
-		res = read(dahdip->fd, pvt->outbuf.uc + pvt->datalen, pvt->t->buf_size - pvt->datalen);
-		if (-1 == res) {
-			if (EWOULDBLOCK == errno) {
-				/* Nothing waiting... */
-				return NULL;
-			} else {
-				ast_log(LOG_ERROR, "Failed to read from /dev/dahdi/transcode: %s\n", strerror(errno));
-				return NULL;
-			}
-		} else {
-			pvt->f.samples = dahdip->samples;
-			pvt->f.datalen = res;
-			pvt->datalen = 0;
-			pvt->f.frametype = AST_FRAME_VOICE;
-			pvt->f.subclass = 1 <<  (pvt->t->dstfmt);
-			pvt->f.mallocd = 0;
-			pvt->f.offset = AST_FRIENDLY_OFFSET;
-			pvt->f.src = pvt->t->name;
-			pvt->f.data.ptr = pvt->outbuf.uc;
-			ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
-
-			return &pvt->f;
-		}
-
-	} else if (2 == dahdip->fake) {
-
+		return 0;
+	}
+
+	/* Buffer up the packets and send them to the hardware if we
+	 * have enough samples set up. */
+	if (dahdip->softslin) {
+		if (lintoulaw(pvt, f)) {
+			 return -1;
+		}
+	} else {
+		/* NOTE:  If softslin support is not needed, and the sample
+		 * size is equal to the required sample size, we wouldn't
+		 * need this copy operation.  But at the time this was
+		 * written, only softslin is supported. */
+		if (dahdip->samples_in_buffer + f->samples > sizeof(dahdip->ulaw_buffer)) {
+			ast_log(LOG_ERROR, "Out of buffer space.\n");
+			return -1;
+		}
+		memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->data.ptr, f->samples);
+		dahdip->samples_in_buffer += f->samples;
+	}
+
+	while (dahdip->samples_in_buffer > dahdip->required_samples) {
+		dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples);
+		dahdip->samples_in_buffer -= dahdip->required_samples;
+		if (dahdip->samples_in_buffer) {
+			/* Shift any remaining bytes down. */
+			memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples],
+				dahdip->samples_in_buffer);
+		}
+	}
+	pvt->samples += f->samples;
+	pvt->datalen = 0;
+	return -1;
+}
+
+static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
+{
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+	int res;
+
+	if (2 == dahdip->fake) {
 		dahdip->fake = 1;
 		pvt->f.frametype = AST_FRAME_VOICE;
 		pvt->f.subclass = 0;
-		pvt->f.samples = 160;
+		pvt->f.samples = dahdip->required_samples;
 		pvt->f.data.ptr = NULL;
 		pvt->f.offset = 0;
 		pvt->f.datalen = 0;
@@ -186,17 +241,128 @@
 		return &pvt->f;
 
 	} else if (1 == dahdip->fake) {
-
+		dahdip->fake = 0;
 		return NULL;
-
-	}
+	}
+
+	res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
+	if (-1 == res) {
+		if (EWOULDBLOCK == errno) {
+			/* Nothing waiting... */
+			return NULL;
+		} else {
+			ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
+			return NULL;
+		}
+	} else {
+		pvt->f.datalen = res;
+		pvt->f.samples = dahdip->required_samples;
+		pvt->f.frametype = AST_FRAME_VOICE;
+		pvt->f.subclass = 1 <<  (pvt->t->dstfmt);
+		pvt->f.mallocd = 0;
+		pvt->f.offset = AST_FRIENDLY_OFFSET;
+		pvt->f.src = pvt->t->name;
+		pvt->f.data.ptr = pvt->outbuf.c;
+		ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
+
+		pvt->samples = 0;
+		pvt->datalen = 0;
+		return &pvt->f;
+	}
+
 	/* Shouldn't get here... */
 	return NULL;
 }
 
+static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+
+	if (!f->subclass) {
+		/* We're just faking a return for calculation purposes. */
+		dahdip->fake = 2;
+		pvt->samples = f->samples;
+		return 0;
+	}
+
+	if (!f->datalen) {
+		if (f->samples != dahdip->required_samples) {
+			ast_log(LOG_ERROR, "%d != %d %d\n", f->samples, dahdip->required_samples, f->datalen);
+		}
+	}
+	dahdi_write_frame(dahdip, f->data.ptr, f->datalen);
+	pvt->samples += f->samples;
+	pvt->datalen = 0;
+	return -1;
+}
+
+static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
+{
+	int res;
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
+
+	if (2 == dahdip->fake) {
+		dahdip->fake = 1;
+		pvt->f.frametype = AST_FRAME_VOICE;
+		pvt->f.subclass = 0;
+		pvt->f.samples = dahdip->required_samples;
+		pvt->f.data.ptr = NULL;
+		pvt->f.offset = 0;
+		pvt->f.datalen = 0;
+		pvt->f.mallocd = 0;
+		ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
+		pvt->samples = 0;
+		return &pvt->f;
+	} else if (1 == dahdip->fake) {
+		pvt->samples = 0;
+		dahdip->fake = 0;
+		return NULL;
+	}
+
+	/* Let's check to see if there is a new frame for us.... */
+	if (dahdip->softslin) {
+		res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer));
+	} else {
+		res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
+	}
+
+	if (-1 == res) {
+		if (EWOULDBLOCK == errno) {
+			/* Nothing waiting... */
+			return NULL;
+		} else {
+			ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
+			return NULL;
+		}
+	} else {
+		if (dahdip->softslin) {
+			ulawtolin(pvt);
+			pvt->f.datalen = res * 2;
+		} else {
+			pvt->f.datalen = res;
+		}
+		pvt->datalen = 0;
+		pvt->f.frametype = AST_FRAME_VOICE;
+		pvt->f.subclass = 1 <<  (pvt->t->dstfmt);
+		pvt->f.mallocd = 0;
+		pvt->f.offset = AST_FRIENDLY_OFFSET;
+		pvt->f.src = pvt->t->name;
+		pvt->f.data.ptr = pvt->outbuf.c;
+		pvt->f.samples = dahdip->required_samples;
+		ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
+		pvt->samples = 0;
+
+		return &pvt->f;
+	}
+
+	/* Shouldn't get here... */
+	return NULL;
+}
+
+
 static void dahdi_destroy(struct ast_trans_pvt *pvt)
 {
-	struct pvt *dahdip = pvt->pvt;
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
 
 	switch (dahdip->fmts.dstfmt) {
 	case AST_FORMAT_G729A:
@@ -215,20 +381,44 @@
 {
 	/* Request translation through zap if possible */
 	int fd;
-	struct pvt *dahdip = pvt->pvt;
+	struct codec_dahdi_pvt *dahdip = pvt->pvt;
 	int flags;
-	
-	if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) {
-		ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno));
+	int tried_once = 0;
+	const char *dev_filename = "/dev/dahdi/transcode";
+
+	if ((fd = open(dev_filename, O_RDWR)) < 0) {
+		ast_log(LOG_ERROR, "Failed to open %s: %s\n", dev_filename, strerror(errno));
 		return -1;
 	}
-	
+
 	dahdip->fmts.srcfmt = (1 << source);
 	dahdip->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, &dahdip->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 == dahdip->fmts.srcfmt) {
+				ast_log(LOG_DEBUG, "Using soft_slin support on source\n");
+				dahdip->softslin = 1;
+				dahdip->fmts.srcfmt = AST_FORMAT_ULAW;
+			} else if (AST_FORMAT_SLINEAR == dahdip->fmts.dstfmt) {
+				ast_log(LOG_DEBUG, "Using soft_slin support on destination\n");
+				dahdip->softslin = 1;
+				dahdip->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);
 
@@ -243,16 +433,16 @@
 
 	dahdip->fd = fd;
 
+	dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt)&AST_FORMAT_G723_1) ? G723_SAMPLES : G729_SAMPLES;
+
 	switch (dahdip->fmts.dstfmt) {
 	case AST_FORMAT_G729A:
-		dahdip->samples = 160;
+		ast_atomic_fetchadd_int(&channels.encoders, +1);
 		break;
 	case AST_FORMAT_G723_1:
-		dahdip->samples = 240;
 		ast_atomic_fetchadd_int(&channels.encoders, +1);
 		break;
 	default:
-		dahdip->samples = 160;
 		ast_atomic_fetchadd_int(&channels.decoders, +1);
 		break;
 	}
@@ -277,33 +467,65 @@
 	return &f;
 }
 
+static int is_encoder(struct translator *zt)
+{
+	if (zt->t.srcfmt&(AST_FORMAT_ULAW|AST_FORMAT_ALAW|AST_FORMAT_SLINEAR)) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 static int register_translator(int dst, int src)
 {
-	struct translator *dahdi;
+	struct translator *zt;
 	int res;
 
-	if (!(dahdi = ast_calloc(1, sizeof(*dahdi))))
+	if (!(zt = ast_calloc(1, sizeof(*zt)))) {
 		return -1;
-
-	snprintf((char *) (dahdi->t.name), sizeof(dahdi->t.name), "dahdi%sto%s", 
+	}
+
+	snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s",
 		 ast_getformatname((1 << src)), ast_getformatname((1 << dst)));
-	dahdi->t.srcfmt = (1 << src);
-	dahdi->t.dstfmt = (1 << dst);
-	dahdi->t.newpvt = dahdi_new;
-	dahdi->t.framein = dahdi_framein;
-	dahdi->t.frameout = dahdi_frameout;
-	dahdi->t.destroy = dahdi_destroy;
-	dahdi->t.sample = fakesrc_sample;
-	dahdi->t.useplc = global_useplc;
-	dahdi->t.buf_size = BUFFER_SAMPLES * 2;
-	dahdi->t.desc_size = sizeof(struct pvt);
-	if ((res = ast_register_translator(&dahdi->t))) {
-		ast_free(dahdi);
+	zt->t.srcfmt = (1 << src);
+	zt->t.dstfmt = (1 << dst);
+	zt->t.buf_size = BUFFER_SIZE;
+	if (is_encoder(zt)) {
+		zt->t.framein = dahdi_encoder_framein;
+		zt->t.frameout = dahdi_encoder_frameout;
+#if 0
+		zt->t.buffer_samples = 0;
+#endif
+	} else {
+		zt->t.framein = dahdi_decoder_framein;
+		zt->t.frameout = dahdi_decoder_frameout;
+#if 0
+		if (AST_FORMAT_G723_1 == zt->t.srcfmt) {
+			zt->t.plc_samples = G723_SAMPLES;
+		} else {
+			zt->t.plc_samples = G729_SAMPLES;
+		}
+		zt->t.buffer_samples = zt->t.plc_samples * 8;
+#endif
+	}
+	zt->t.destroy = dahdi_destroy;
+	zt->t.buffer_samples = 0;
+	zt->t.newpvt = dahdi_new;
+	zt->t.sample = fakesrc_sample;
+#if 0
+	zt->t.useplc = global_useplc;
+#endif
+	zt->t.useplc = 0;
+	zt->t.native_plc = 0;
+
+	zt->t.desc_size = sizeof(struct codec_dahdi_pvt);
+	if ((res = ast_register_translator(&zt->t))) {
+		ast_free(zt);
 		return -1;
 	}
 
 	AST_LIST_LOCK(&translators);
-	AST_LIST_INSERT_HEAD(&translators, dahdi, entry);
+	AST_LIST_INSERT_HEAD(&translators, zt, entry);
 	AST_LIST_UNLOCK(&translators);
 
 	global_format_map.map[dst][src] = 1;
@@ -335,12 +557,12 @@
 
 static void unregister_translators(void)
 {
-	struct translator *current;
+	struct translator *cur;
 
 	AST_LIST_LOCK(&translators);
-	while ((current = AST_LIST_REMOVE_HEAD(&translators, entry))) {
-		ast_unregister_translator(&current->t);
-		ast_free(current);
+	while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
+		ast_unregister_translator(&cur->t);
+		ast_free(cur);
 	}
 	AST_LIST_UNLOCK(&translators);
 }
@@ -357,10 +579,11 @@
 	for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
 	       if (!strcasecmp(var->name, "genericplc")) {
 		       global_useplc = ast_true(var->value);
-			   ast_verb(3, "codec_dahdi: %susing generic PLC\n",
-					   global_useplc ? "" : "not ");
+		       ast_verb(3, "codec_dahdi: %susing generic PLC\n",
+				global_useplc ? "" : "not ");
 	       }
 	}
+
 	ast_config_destroy(cfg);
 	return 0;
 }
@@ -401,8 +624,25 @@
 	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. Also, do not allow direct ulaw/alaw to complex
+		 * codec translation, since that will prevent the generic PLC
+		 * functions from working. */
+		if (info.dstfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) {
+			info.dstfmts |= AST_FORMAT_SLINEAR;
+			info.dstfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW);
+		}
+		if (info.srcfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) {
+			info.srcfmts |= AST_FORMAT_SLINEAR;
+			info.srcfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW);
+		}
+
 		build_translators(&map, info.dstfmts, info.srcfmts);
 		ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2);
+
 	}
 
 	close(fd);
@@ -445,6 +685,7 @@
 
 static int load_module(void)
 {
+	ast_ulaw_init();
 	if (parse_config(0))
 		return AST_MODULE_LOAD_DECLINE;
 	find_transcoders();
@@ -456,4 +697,4 @@
 		.load = load_module,
 		.unload = unload_module,
 		.reload = reload,
-		);
+	       );

Modified: team/group/newcdr/include/asterisk/channel.h
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/include/asterisk/channel.h?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/include/asterisk/channel.h (original)
+++ team/group/newcdr/include/asterisk/channel.h Wed Feb 18 09:05:41 2009
@@ -577,6 +577,7 @@
 	AST_FEATURE_PARKCALL =     (1 << 5),
 	AST_FEATURE_AUTOMIXMON =   (1 << 6),
 	AST_FEATURE_NO_H_EXTEN =   (1 << 7),
+	AST_FEATURE_WARNING_ACTIVE = (1 << 7),
 };
 
 /*! \brief bridge configuration */
@@ -584,6 +585,7 @@
 	struct ast_flags features_caller;
 	struct ast_flags features_callee;
 	struct timeval start_time;
+	struct timeval nexteventts;
 	long feature_timer;
 	long timelimit;
 	long play_warning;

Modified: team/group/newcdr/include/asterisk/heap.h
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/include/asterisk/heap.h?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/include/asterisk/heap.h (original)
+++ team/group/newcdr/include/asterisk/heap.h Wed Feb 18 09:05:41 2009
@@ -155,6 +155,28 @@
  * \note If this function is being used in combination with ast_heap_size() for
  *       purposes of traversing the heap, the heap must be locked for the entire
  *       duration of the traversal.
+ *
+ * Example code for a traversal:
+ * \code
+ *
+ * struct ast_heap *h;
+ *
+ * ...
+ *
+ * size_t size, i;
+ * void *cur_obj;
+ *
+ * ast_heap_rdlock(h);
+ *
+ * size = ast_heap_size(h);
+ *
+ * for (i = 1; i <= size && (cur_obj = ast_heap_peek(h, i)); i++) {
+ *     ... Do stuff with cur_obj ...
+ * }
+ *
+ * ast_heap_unlock(h);
+ *
+ * \endcode
  */
 void *ast_heap_peek(struct ast_heap *h, unsigned int index);
 

Modified: team/group/newcdr/main/channel.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/main/channel.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/main/channel.c (original)
+++ team/group/newcdr/main/channel.c Wed Feb 18 09:05:41 2009
@@ -4638,10 +4638,13 @@
 		if (bridge_end.tv_sec) {
 			to = ast_tvdiff_ms(bridge_end, ast_tvnow());
 			if (to <= 0) {
-				if (config->timelimit)
+				if (config->timelimit) {
 					res = AST_BRIDGE_RETRY;
-				else
+					/* generic bridge ending to play warning */
+					ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
+				} else {
 					res = AST_BRIDGE_COMPLETE;
+				}
 				break;
 			}
 		} else
@@ -4720,6 +4723,7 @@
 				ast_debug(1, "Got DTMF %s on channel (%s)\n", 
 					f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
 					who->name);
+
 				break;
 			}
 			/* Write immediately frames, not passed through jb */
@@ -4791,7 +4795,6 @@
 	int o0nativeformats;
 	int o1nativeformats;
 	long time_left_ms=0;
-	struct timeval nexteventts = { 0, };
 	char caller_warning = 0;
 	char callee_warning = 0;
 
@@ -4839,11 +4842,11 @@
 	o1nativeformats = c1->nativeformats;
 
 	if (config->feature_timer) {
-		nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
-	} else if (config->timelimit) {
-		nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
+		config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
+	} else if (config->timelimit && firstpass) {
+		config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
 		if (caller_warning || callee_warning)
-			nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000));
+			config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(config->play_warning, 1000));
 	}
 
 	if (!c0->tech->send_digit_begin)
@@ -4863,9 +4866,9 @@
 
 		to = -1;
 
-		if (!ast_tvzero(nexteventts)) {
+		if (!ast_tvzero(config->nexteventts)) {
 			now = ast_tvnow();
-			to = ast_tvdiff_ms(nexteventts, now);
+			to = ast_tvdiff_ms(config->nexteventts, now);
 			if (to <= 0) {
 				if (!config->timelimit) {
 					res = AST_BRIDGE_COMPLETE;
@@ -4893,7 +4896,7 @@
 			}
 			
 			if (!to) {
-				if (time_left_ms >= 5000 && config->warning_sound && config->play_warning) {
+				if (time_left_ms >= 5000 && config->warning_sound && config->play_warning && ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
 					int t = (time_left_ms + 500) / 1000; /* round to nearest second */
 					if (caller_warning)
 						bridge_playfile(c0, c1, config->warning_sound, t);
@@ -4901,10 +4904,11 @@
 						bridge_playfile(c1, c0, config->warning_sound, t);
 				}
 				if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000)))
-					nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000));
+					config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000));
 				else
-					nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
+					config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
 			}
+			ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
 		}
 
 		if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
@@ -5019,9 +5023,13 @@
 		if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER")))
 			pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0->name);
 
-		res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts);
-		if (res != AST_BRIDGE_RETRY)
+		res = ast_generic_bridge(c0, c1, config, fo, rc, config->nexteventts);
+		if (res != AST_BRIDGE_RETRY) {
 			break;
+		} else if (config->feature_timer) {
+			/* feature timer expired but has not been updated, sending to ast_bridge_call to do so */
+			break;
+		}
 	}
 
 	ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY);

Modified: team/group/newcdr/main/features.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/main/features.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/main/features.c (original)
+++ team/group/newcdr/main/features.c Wed Feb 18 09:05:41 2009
@@ -2577,6 +2577,15 @@
 		if (config->feature_timer) {
 			/* Update time limit for next pass */
 			diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
+			if (res == AST_BRIDGE_RETRY) {
+				/* The feature fully timed out but has not been updated. Skip
+				 * the potential round error from the diff calculation and
+				 * explicitly set to expired. */
+				config->feature_timer = -1;
+			} else {
+				config->feature_timer -= diff;
+			}
+
 			config->feature_timer -= diff;
 			if (hasfeatures) {
 				/* Running on backup config, meaning a feature might be being

Modified: team/group/newcdr/main/pbx.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/main/pbx.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/main/pbx.c (original)
+++ team/group/newcdr/main/pbx.c Wed Feb 18 09:05:41 2009
@@ -1862,7 +1862,8 @@
 	int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
 	
 
-	strncpy(extenbuf,e1->exten,sizeof(extenbuf));
+	ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
+
 	if (e1->matchcid &&  l1 <= sizeof(extenbuf)) {
 		strcat(extenbuf,"/");
 		strcat(extenbuf,e1->cidmatch);
@@ -2390,7 +2391,9 @@
 {
 	struct ast_context *tmp = NULL;
 	struct fake_context item;
-	strncpy(item.name,name,256);
+
+	ast_copy_string(item.name, name, sizeof(item.name));
+
 	ast_rdlock_contexts();
 	if( contexts_table ) {
 		tmp = ast_hashtab_lookup(contexts_table,&item);
@@ -2462,8 +2465,10 @@
 		tmp = bypass;
 	else {	/* look in contexts */
 		struct fake_context item;
-		strncpy(item.name,context,256);
-		tmp = ast_hashtab_lookup(contexts_table,&item);
+
+		ast_copy_string(item.name, context, sizeof(item.name));
+
+		tmp = ast_hashtab_lookup(contexts_table, &item);
 #ifdef NOTNOW
 		tmp = NULL;
 		while ((tmp = ast_walk_contexts(tmp)) ) {
@@ -4904,7 +4909,8 @@
 
 	ast_rdlock_contexts();
 
-	strncpy(item.name,context,256);
+	ast_copy_string(item.name, context, sizeof(item.name));
+
 	c = ast_hashtab_lookup(contexts_table,&item);
 	if (c)
 		ret = 0;
@@ -4942,7 +4948,8 @@
 
 	ast_rdlock_contexts();
 
-	strncpy(item.name, context, 256);
+	ast_copy_string(item.name, context, sizeof(item.name));
+
 	c = ast_hashtab_lookup(contexts_table,&item);
 	if (c)
 		ret = 0;
@@ -6313,7 +6320,7 @@
 										   0);
 	}
 	
-	strncpy(search.name,name,sizeof(search.name));
+	ast_copy_string(search.name, name, sizeof(search.name));
 	if (!extcontexts) {
 		ast_rdlock_contexts();
 		local_contexts = &contexts;
@@ -7544,7 +7551,7 @@
 	
 	if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
 								an extension, and the trie exists, then we need to incrementally add this pattern to it. */
-		strncpy(dummy_name,extension,sizeof(dummy_name));
+		ast_copy_string(dummy_name, extension, sizeof(dummy_name));
 		dummy_exten.exten = dummy_name;
 		dummy_exten.matchcid = 0;
 		dummy_exten.cidmatch = 0;

Modified: team/group/newcdr/main/rtp.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/newcdr/main/rtp.c?view=diff&rev=176942&r1=176941&r2=176942
==============================================================================
--- team/group/newcdr/main/rtp.c (original)
+++ team/group/newcdr/main/rtp.c Wed Feb 18 09:05:41 2009
@@ -3735,16 +3735,27 @@
 		rtp->smoother = NULL;
 	}
 
-	if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
+	if (!rtp->smoother) {
 		struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
-		if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
-			if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
-				ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
-				return -1;
+
+		switch (subclass) {
+		case AST_FORMAT_SPEEX:
+		case AST_FORMAT_G723_1:
+		case AST_FORMAT_SIREN7:
+		case AST_FORMAT_SIREN14:
+			/* these are all frame-based codecs and cannot be safely run through
+			   a smoother */
+			break;
+		default:
+			if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
+				if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
+					ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+					return -1;
+				}
+				if (fmt.flags)
+					ast_smoother_set_flags(rtp->smoother, fmt.flags);
+				ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
 			}
-			if (fmt.flags)
-				ast_smoother_set_flags(rtp->smoother, fmt.flags);
-			ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
 		}
 	}
 	if (rtp->smoother) {




More information about the asterisk-commits mailing list