[asterisk-commits] dvossel: branch dvossel/celt_codec_ftw r313141 - in /team/dvossel/celt_codec_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 8 17:51:48 CDT 2011


Author: dvossel
Date: Fri Apr  8 17:51:44 2011
New Revision: 313141

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=313141
Log:
Bug fix for ast_write with multiple frames being returned from translator

Modified:
    team/dvossel/celt_codec_ftw/codecs/codec_celt.c
    team/dvossel/celt_codec_ftw/codecs/codec_resample.c
    team/dvossel/celt_codec_ftw/main/channel.c

Modified: team/dvossel/celt_codec_ftw/codecs/codec_celt.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/celt_codec_ftw/codecs/codec_celt.c?view=diff&rev=313141&r1=313140&r2=313141
==============================================================================
--- team/dvossel/celt_codec_ftw/codecs/codec_celt.c (original)
+++ team/dvossel/celt_codec_ftw/codecs/codec_celt.c Fri Apr  8 17:51:44 2011
@@ -36,6 +36,7 @@
 #include "asterisk/translate.h"
 #include "asterisk/module.h"
 #include "asterisk/utils.h"
+#include "asterisk/linkedlists.h"
 
 #define OUTBUF_SIZE   8096
 
@@ -58,17 +59,26 @@
 	CELTMode *mode;
 	CELTEncoder *enc;
 	SpeexResamplerState *resamp;
-
+	int16_t slin_buf[OUTBUF_SIZE];
+	unsigned slin_samples;
+	unsigned int frame_size;
+	unsigned int sample_rate;
 	/*! Number of current valid out frame buffers */
 	unsigned int frame_offsets_num;
 	/* Pointers to the beginning of each valid outframe */
-	char *frame_offsets[MAX_ENC_RETURN_FRAMES];
+	struct {
+		unsigned char *buf;
+		unsigned int len;
+	} frame_offsets[MAX_ENC_RETURN_FRAMES];
 };
 struct celt_decoder_pvt {
 	int init;
 	CELTMode *mode;
 	CELTDecoder *dec;
 	SpeexResamplerState *resamp;
+	unsigned int frame_size;
+	int16_t slin_buf[OUTBUF_SIZE];
+	unsigned slin_samples;
 };
 
 static int celt_enc_set(struct ast_trans_pvt *pvt, struct ast_format *slin_src)
@@ -88,20 +98,27 @@
 	}
 
 	if (slin_rate != celt_rate) {
-		/*TODO if src rate not equal dst rate, magic */
+		if (!(enc->resamp = speex_resampler_init(1, slin_rate, celt_rate, 5, &error))) {
+			return -1;
+		}
 	}
 
 	if (!(enc->mode = celt_mode_create(celt_rate, frame_size, &error))) {
 		ast_log(LOG_WARNING, "Failed to create CELT encoder mode, error code %d\n", error);
+		speex_resampler_destroy(enc->resamp);
 		return -1;
 	}
 
 	if (!(enc->enc = celt_encoder_create(enc->mode, 1, &error))) {
 		ast_log(LOG_WARNING, "Failed to create CELT encoder, error code %d\n", error);
+		speex_resampler_destroy(enc->resamp);
 		celt_mode_destroy(enc->mode);
 		enc->mode = NULL;
 		return -1;
 	}
+
+	enc->frame_size = frame_size;
+	enc->sample_rate = celt_rate;
 
 	enc->init = 1;
 
@@ -122,11 +139,14 @@
 	}
 
 	if (slin_rate != celt_rate) {
-		/*TODO if src rate not equal dst rate, magic */
+		if (!(dec->resamp = speex_resampler_init(1, celt_rate, slin_rate, 5, &error))) {
+			return -1;
+		}
 	}
 
 	if (!(dec->mode = celt_mode_create(celt_rate, frame_size, &error))) {
 		ast_log(LOG_WARNING, "Failed to create CELT decoder mode, error code %d\n", error);
+		speex_resampler_destroy(dec->resamp);
 		return -1;
 	}
 
@@ -134,8 +154,12 @@
 		ast_log(LOG_WARNING, "Failed to create CELT decoder, error code %d\n", error);
 		celt_mode_destroy(dec->mode);
 		dec->mode = NULL;
-		return -1;
-	}
+		speex_resampler_destroy(dec->resamp);
+		return -1;
+	}
+
+
+	dec->frame_size = frame_size;
 
 	dec->init = 1;
 
@@ -179,13 +203,61 @@
 
 static int celt_enc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
 {
-	struct celt_decoder_pvt *enc = pvt->pvt;
+	struct celt_encoder_pvt *enc = pvt->pvt;
+	int16_t *slin_data;
+	unsigned char *celt_data;
+	int num_bytes = 0;
 
 	if (!enc->init) {
 		celt_enc_set(pvt, &f->subclass.format);
 	}
 
-	/* TODO make awesome stuff happen here */
+	if (!f->datalen) {
+		return -1;
+	}
+
+	/* bring the slin to the native celt rate we want to encode */
+	if (enc->resamp) {
+		unsigned int in_samples = f->samples;
+		unsigned int out_samples = OUTBUF_SIZE - enc->slin_samples;
+		speex_resampler_process_int(enc->resamp,
+			0,
+			f->data.ptr,
+			&in_samples,
+			enc->slin_buf + enc->slin_samples,
+			&out_samples);
+
+		enc->slin_samples += out_samples;
+	} else {
+		memcpy(enc->slin_buf + enc->slin_samples, f->data.ptr, f->datalen);
+		enc->slin_samples += (f->datalen / 2);
+	}
+
+	slin_data = enc->slin_buf;
+	celt_data = (unsigned char *) pvt->outbuf.c;
+
+	for ( ; enc->slin_samples >= enc->frame_size; enc->slin_samples -= enc->frame_size) {
+		num_bytes = celt_encode(enc->enc, slin_data, enc->frame_size, celt_data, 960);
+
+		if (num_bytes <= 0) {
+			/* err */
+			break;
+		}
+
+		if (enc->frame_offsets_num >= MAX_ENC_RETURN_FRAMES) {
+			break;
+		}
+
+		enc->frame_offsets[enc->frame_offsets_num].buf = celt_data;
+		enc->frame_offsets[enc->frame_offsets_num].len = num_bytes;
+		enc->frame_offsets_num++;
+
+		pvt->samples += enc->frame_size;
+
+		slin_data += enc->frame_size; /* increments by int16_t samples */
+		celt_data += num_bytes; /* increments by bytes */
+	}
+
 	return 0;
 }
 
@@ -193,11 +265,39 @@
 {
 	struct celt_encoder_pvt *enc = pvt->pvt;
 	struct ast_frame *frame = NULL;
-
-	/* TODO make frame here.  It is possible multiple CELT frames will get returned. */
+	struct ast_frame *cur = NULL;
+	struct ast_frame tmp;
+	int i;
+
+	for (i = 0; i < enc->frame_offsets_num; i++) {
+		memset(&tmp, 0, sizeof(tmp));
+		tmp.frametype = AST_FRAME_VOICE;
+		if (pvt->explicit_dst.id) {
+			ast_format_copy(&tmp.subclass.format, &pvt->explicit_dst);
+		} else {
+			ast_format_set(&tmp.subclass.format, AST_FORMAT_CELT,
+				CELT_ATTR_KEY_SAMP_RATE, enc->sample_rate,
+				CELT_ATTR_KEY_FRAME_SIZE, enc->frame_size);
+		}
+		tmp.datalen = enc->frame_offsets[i].len;
+		tmp.data.ptr = enc->frame_offsets[i].buf;
+		tmp.samples = enc->frame_size;
+		tmp.src = pvt->t->name;
+		tmp.offset = AST_FRIENDLY_OFFSET;
+
+		if (frame) {
+			AST_LIST_NEXT(cur, frame_list) = ast_frisolate(&tmp);
+			cur = AST_LIST_NEXT(cur, frame_list);
+		} else {
+			frame = ast_frisolate(&tmp);
+			cur = frame;
+		}
+	}
+
+
+	pvt->samples = 0;
 	memset(enc->frame_offsets, 0, sizeof(enc->frame_offsets));
 	enc->frame_offsets_num = 0;
-
 	return frame;
 }
 
@@ -205,22 +305,59 @@
 static int celt_dec_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
 {
 	struct celt_decoder_pvt *dec = pvt->pvt;
+	int error;
 	if (!dec->init) {
 		celt_dec_set(pvt, &f->subclass.format);
 	}
 
-	/* TODO make awesome stuff happen here */
+	error = celt_decode(dec->dec, f->data.ptr, f->datalen, dec->slin_buf, dec->frame_size);
+	if (error) {
+		ast_log(LOG_WARNING, "error decoding CELT, error code %d\n", error);
+		return -1;
+	}
+
+	dec->slin_samples = dec->frame_size;
+	pvt->samples = dec->frame_size;
+
 	return 0;
 }
 
 
 static struct ast_frame *celt_dec_frameout(struct ast_trans_pvt *pvt)
 {
-	//struct celt_decoder_pvt *dec = pvt->pvt;
-	struct ast_frame *frame = NULL;
-
-	/* TODO make  slin frame here. */
-	return frame;
+	struct celt_decoder_pvt *dec = pvt->pvt;
+	struct ast_frame tmp;
+	int16_t *outslin = dec->slin_buf;
+	unsigned int samples = dec->slin_samples;
+
+
+	if (dec->resamp) {
+		unsigned int in_samples = samples;
+		unsigned int out_samples = OUTBUF_SIZE;
+		speex_resampler_process_int(dec->resamp,
+			0,
+			dec->slin_buf,
+			&in_samples,
+			pvt->outbuf.i16,
+			&out_samples);
+		samples = out_samples;
+		outslin = pvt->outbuf.i16;
+	}
+
+	if (!samples) {
+		return NULL;
+	}
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.frametype = AST_FRAME_VOICE;
+	ast_format_copy(&tmp.subclass.format, &pvt->t->dst_format);
+	tmp.datalen = samples * 2;
+	tmp.data.ptr = outslin;
+	tmp.samples = samples;
+	tmp.src = pvt->t->name;
+	tmp.offset = AST_FRIENDLY_OFFSET;
+
+	pvt->samples = 0;
+	return ast_frdup(&tmp);
 }
 
 

Modified: team/dvossel/celt_codec_ftw/codecs/codec_resample.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/celt_codec_ftw/codecs/codec_resample.c?view=diff&rev=313141&r1=313140&r2=313141
==============================================================================
--- team/dvossel/celt_codec_ftw/codecs/codec_resample.c (original)
+++ team/dvossel/celt_codec_ftw/codecs/codec_resample.c Fri Apr  8 17:51:44 2011
@@ -73,6 +73,10 @@
 	unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
 	unsigned int in_samples = f->samples;
 
+	if (!f->datalen) {
+		return -1;
+	}
+
 	speex_resampler_process_int(resamp_pvt,
 		0,
 		f->data.ptr,

Modified: team/dvossel/celt_codec_ftw/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/celt_codec_ftw/main/channel.c?view=diff&rev=313141&r1=313140&r2=313141
==============================================================================
--- team/dvossel/celt_codec_ftw/main/channel.c (original)
+++ team/dvossel/celt_codec_ftw/main/channel.c Fri Apr  8 17:51:44 2011
@@ -4954,12 +4954,13 @@
 		   from the single frame we passed in; if so, feed each one of them to the
 		   channel, freeing each one after it has been written */
 		if ((f != fr) && AST_LIST_NEXT(f, frame_list)) {
-			struct ast_frame *cur, *next;
+			struct ast_frame *cur, *next = NULL;
 			unsigned int skip = 0;
 
-			for (cur = f, next = AST_LIST_NEXT(cur, frame_list);
-			     cur;
-			     cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) {
+			cur = f;
+			while (cur) {
+				next = AST_LIST_NEXT(cur, frame_list);
+				AST_LIST_NEXT(cur, frame_list) = NULL;
 				if (!skip) {
 					if ((res = chan->tech->write(chan, cur)) < 0) {
 						chan->_softhangup |= AST_SOFTHANGUP_DEV;
@@ -4972,6 +4973,7 @@
 					}
 				}
 				ast_frfree(cur);
+				cur = next;
 			}
 
 			/* reset f so the code below doesn't attempt to free it */




More information about the asterisk-commits mailing list