[Asterisk-cvs] asterisk frame.c,1.52,1.53 rtp.c,1.126,1.127

markster at lists.digium.com markster at lists.digium.com
Sat May 14 19:52:14 CDT 2005


Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv32412

Modified Files:
	frame.c rtp.c 
Log Message:
Add remainder of rtp fixes, iax2 patch (bug #3961)


Index: frame.c
===================================================================
RCS file: /usr/cvsroot/asterisk/frame.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- frame.c	22 Apr 2005 13:11:34 -0000	1.52
+++ frame.c	14 May 2005 23:57:44 -0000	1.53
@@ -35,6 +35,12 @@
 
 #define SMOOTHER_SIZE 8000
 
+#define TYPE_HIGH	 0x0
+#define TYPE_LOW	 0x1
+#define TYPE_SILENCE	 0x2
+#define TYPE_DONTSEND	 0x3
+#define TYPE_MASK	 0x3
+
 struct ast_format_list {
 	int visible; /* Can we see this entry */
 	int bits; /* bitmask value */
@@ -1008,4 +1014,190 @@
 	}
 }
 
+static int g723_len(unsigned char buf)
+{
+	switch(buf & TYPE_MASK) {
+	case TYPE_DONTSEND:
+		return 0;
+		break;
+	case TYPE_SILENCE:
+		return 4;
+		break;
+	case TYPE_HIGH:
+		return 24;
+		break;
+	case TYPE_LOW:
+		return 20;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
+	}
+	return -1;
+}
+
+static int g723_samples(unsigned char *buf, int maxlen)
+{
+	int pos = 0;
+	int samples = 0;
+	int res;
+	while(pos < maxlen) {
+		res = g723_len(buf[pos]);
+		if (res <= 0)
+			break;
+		samples += 240;
+		pos += res;
+	}
+	return samples;
+}
+
+static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
+{
+	int byte = bit / 8;       /* byte containing first bit */
+	int rem = 8 - (bit % 8);  /* remaining bits in first byte */
+	unsigned char ret = 0;
+	
+	if (n <= 0 || n > 8)
+		return 0;
+
+	if (rem < n) {
+		ret = (data[byte] << (n - rem));
+		ret |= (data[byte + 1] >> (8 - n + rem));
+	} else {
+		ret = (data[byte] >> (rem - n));
+	}
+
+	return (ret & (0xff >> (8 - n)));
+}
+
+static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
+{
+	static int SpeexWBSubModeSz[] = {
+		0, 36, 112, 192,
+		352, 0, 0, 0 };
+	int off = bit;
+	unsigned char c;
+
+	/* skip up to two wideband frames */
+	if (((len * 8 - off) >= 5) && 
+		get_n_bits_at(data, 1, off)) {
+		c = get_n_bits_at(data, 3, off + 1);
+		off += SpeexWBSubModeSz[c];
+
+		if (((len * 8 - off) >= 5) && 
+			get_n_bits_at(data, 1, off)) {
+			c = get_n_bits_at(data, 3, off + 1);
+			off += SpeexWBSubModeSz[c];
+
+			if (((len * 8 - off) >= 5) && 
+				get_n_bits_at(data, 1, off)) {
+				ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
+				return -1;
+			}
+		}
+
+	}
+	return off - bit;
+}
+
+static int speex_samples(unsigned char *data, int len)
+{
+	static int SpeexSubModeSz[] = {
+		0, 43, 119, 160, 
+		220, 300, 364, 492, 
+		79, 0, 0, 0,
+		0, 0, 0, 0 };
+	static int SpeexInBandSz[] = { 
+		1, 1, 4, 4,
+		4, 4, 4, 4,
+		8, 8, 16, 16,
+		32, 32, 64, 64 };
+	int bit = 0;
+	int cnt = 0;
+	int off = 0;
+	unsigned char c;
+
+	while ((len * 8 - bit) >= 5) {
+		/* skip wideband frames */
+		off = speex_get_wb_sz_at(data, len, bit);
+		if (off < 0)  {
+			ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
+			break;
+		}
+		bit += off;
+
+		if ((len * 8 - bit) < 5) {
+			ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
+			break;
+		}
+
+		/* get control bits */
+		c = get_n_bits_at(data, 5, bit);
+		bit += 5;
+
+		if (c == 15) { 
+			/* terminator */
+			break; 
+		} else if (c == 14) {
+			/* in-band signal; next 4 bits contain signal id */
+			c = get_n_bits_at(data, 4, bit);
+			bit += 4;
+			bit += SpeexInBandSz[c];
+		} else if (c == 13) {
+			/* user in-band; next 5 bits contain msg len */
+			c = get_n_bits_at(data, 5, bit);
+			bit += 5;
+			bit += c * 8;
+		} else if (c > 8) {
+			/* unknown */
+			break;
+		} else {
+			/* skip number bits for submode (less the 5 control bits) */
+			bit += SpeexSubModeSz[c] - 5;
+			cnt += 160; /* new frame */
+		}
+	}
+	return cnt;
+}
+
+
+int ast_codec_get_samples(struct ast_frame *f)
+{
+	int samples=0;
+	switch(f->subclass) {
+	case AST_FORMAT_SPEEX:
+		samples = speex_samples(f->data, f->datalen);
+		break;
+	case AST_FORMAT_G723_1:
+                samples = g723_samples(f->data, f->datalen);
+		break;
+	case AST_FORMAT_ILBC:
+		samples = 240 * (f->datalen / 50);
+		break;
+	case AST_FORMAT_GSM:
+		samples = 160 * (f->datalen / 33);
+		break;
+	case AST_FORMAT_G729A:
+		samples = f->datalen * 8;
+		break;
+	case AST_FORMAT_SLINEAR:
+		samples = f->datalen / 2;
+		break;
+	case AST_FORMAT_LPC10:
+                /* assumes that the RTP packet contains one LPC10 frame */
+		samples = 22 * 8;
+		samples += (((char *)(f->data))[7] & 0x1) * 8;
+		break;
+	case AST_FORMAT_ULAW:
+	case AST_FORMAT_ALAW:
+		samples = f->datalen;
+		break;
+	case AST_FORMAT_ADPCM:
+	case AST_FORMAT_G726:
+		samples = f->datalen * 2;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
+	}
+	return samples;
+}
 

Index: rtp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/rtp.c,v
retrieving revision 1.126
retrieving revision 1.127
diff -u -d -r1.126 -r1.127
--- rtp.c	14 May 2005 23:41:12 -0000	1.126
+++ rtp.c	14 May 2005 23:57:44 -0000	1.127
@@ -43,12 +43,6 @@
 
 #define RTP_MTU		1200
 
-#define TYPE_HIGH	 0x0
-#define TYPE_LOW	 0x1
-#define TYPE_SILENCE	 0x2
-#define TYPE_DONTSEND	 0x3
-#define TYPE_MASK	 0x3
-
 static int dtmftimeout = 3000;	/* 3000 samples */
 
 static int rtpstart = 0;
@@ -128,42 +122,6 @@
 	return -1;
 }
 
-static int g723_len(unsigned char buf)
-{
-	switch(buf & TYPE_MASK) {
-	case TYPE_DONTSEND:
-		return 0;
-		break;
-	case TYPE_SILENCE:
-		return 4;
-		break;
-	case TYPE_HIGH:
-		return 24;
-		break;
-	case TYPE_LOW:
-		return 20;
-		break;
-	default:
-		ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
-	}
-	return -1;
-}
-
-static int g723_samples(unsigned char *buf, int maxlen)
-{
-	int pos = 0;
-	int samples = 0;
-	int res;
-	while(pos < maxlen) {
-		res = g723_len(buf[pos]);
-		if (res <= 0)
-			break;
-		samples += 240;
-		pos += res;
-	}
-	return samples;
-}
-
 void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
 {
 	rtp->data = data;
@@ -594,43 +552,9 @@
 	rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
 	rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
 	if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
-		switch(rtp->f.subclass) {
-		case AST_FORMAT_ULAW:
-		case AST_FORMAT_ALAW:
-			rtp->f.samples = rtp->f.datalen;
-			break;
-		case AST_FORMAT_SLINEAR:
-			rtp->f.samples = rtp->f.datalen / 2;
+		rtp->f.samples = ast_codec_get_samples(&rtp->f);
+		if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
 			ast_frame_byteswap_be(&rtp->f);
-			break;
-		case AST_FORMAT_GSM:
-			rtp->f.samples = 160 * (rtp->f.datalen / 33);
-			break;
-		case AST_FORMAT_ILBC:
-			rtp->f.samples = 240 * (rtp->f.datalen / 50);
-			break;
-		case AST_FORMAT_ADPCM:
-		case AST_FORMAT_G726:
-			rtp->f.samples = rtp->f.datalen * 2;
-			break;
-		case AST_FORMAT_G729A:
-			rtp->f.samples = rtp->f.datalen * 8;
-			break;
-		case AST_FORMAT_G723_1:
-			rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen);
-			break;
-		case AST_FORMAT_SPEEX:
-			/* assumes that the RTP packet contained one Speex frame */
-	        	rtp->f.samples = 160;
-			break;
-		case AST_FORMAT_LPC10:
-		    	rtp->f.samples = 22 * 8;
-			rtp->f.samples += (((char *)(rtp->f.data))[7] & 0x1) * 8;
-			break;
-		default:
-			ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass));
-			break;
-		}
 		calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
 	} else {
 		/* Video -- samples is # of samples vs. 90000 */
@@ -1233,45 +1157,8 @@
 	ms = calc_txstamp(rtp, &f->delivery);
 	/* Default prediction */
 	if (f->subclass < AST_FORMAT_MAX_AUDIO) {
-		pred = rtp->lastts + ms * 8;
-		
-		switch(f->subclass) {
-		case AST_FORMAT_ULAW:
-		case AST_FORMAT_ALAW:
-			/* If we're within +/- 20ms from when where we
-			   predict we should be, use that */
-			pred = rtp->lastts + f->datalen;
-			break;
-		case AST_FORMAT_ADPCM:
-		case AST_FORMAT_G726:
-			/* If we're within +/- 20ms from when where we
-			   predict we should be, use that */
-			pred = rtp->lastts + f->datalen * 2;
-			break;
-		case AST_FORMAT_G729A:
-			pred = rtp->lastts + f->datalen * 8;
-			break;
-		case AST_FORMAT_GSM:
-			pred = rtp->lastts + (f->datalen * 160 / 33);
-			break;
-		case AST_FORMAT_ILBC:
-			pred = rtp->lastts + (f->datalen * 240 / 50);
-			break;
-		case AST_FORMAT_G723_1:
-			pred = rtp->lastts + g723_samples(f->data, f->datalen);
-			break;
-		case AST_FORMAT_SPEEX:
-		    pred = rtp->lastts + 160;
-			/* assumes that the RTP packet contains one Speex frame */
-			break;
-		case AST_FORMAT_LPC10:
-			/* assumes that the RTP packet contains one LPC10 frame */
-			pred = rtp->lastts + 22 * 8;
-			pred += (((char *)(f->data))[7] & 0x1) * 8;
-			break;
-		default:
-			ast_log(LOG_WARNING, "Not sure about timestamp format for codec format %s\n", ast_getformatname(f->subclass));
-		}
+                pred = rtp->lastts + ast_codec_get_samples(f);
+
 		/* Re-calculate last TS */
 		rtp->lastts = rtp->lastts + ms * 8;
 		if (!f->delivery.tv_sec && !f->delivery.tv_usec) {




More information about the svn-commits mailing list