mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-26 22:30:28 +00:00 
			
		
		
		
	Merge "translate: Fix transcoding while different in frame size." into 13
This commit is contained in:
		| @@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/config.h" | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/utils.h" | ||||
| #include "asterisk/linkedlists.h" | ||||
|  | ||||
| #ifdef HAVE_GSM_HEADER | ||||
| #include "gsm.h" | ||||
| @@ -139,25 +140,35 @@ static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | ||||
| static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt) | ||||
| { | ||||
| 	struct gsm_translator_pvt *tmp = pvt->pvt; | ||||
| 	int datalen = 0; | ||||
| 	int samples = 0; | ||||
| 	struct ast_frame *result = NULL; | ||||
| 	struct ast_frame *last = NULL; | ||||
| 	int samples = 0; /* output samples */ | ||||
|  | ||||
| 	/* We can't work on anything less than a frame in size */ | ||||
| 	if (pvt->samples < GSM_SAMPLES) | ||||
| 		return NULL; | ||||
| 	while (pvt->samples >= GSM_SAMPLES) { | ||||
| 		struct ast_frame *current; | ||||
|  | ||||
| 		/* Encode a frame of data */ | ||||
| 		gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c + datalen); | ||||
| 		datalen += GSM_FRAME_LEN; | ||||
| 		gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c); | ||||
| 		samples += GSM_SAMPLES; | ||||
| 		pvt->samples -= GSM_SAMPLES; | ||||
|  | ||||
| 		current = ast_trans_frameout(pvt, GSM_FRAME_LEN, GSM_SAMPLES); | ||||
| 		if (!current) { | ||||
| 			continue; | ||||
| 		} else if (last) { | ||||
| 			AST_LIST_NEXT(last, frame_list) = current; | ||||
| 		} else { | ||||
| 			result = current; | ||||
| 		} | ||||
| 		last = current; | ||||
| 	} | ||||
|  | ||||
| 	/* Move the data at the end of the buffer to the front */ | ||||
| 	if (pvt->samples) | ||||
| 	if (samples) { | ||||
| 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | ||||
| 	} | ||||
|  | ||||
| 	return ast_trans_frameout(pvt, datalen, samples); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static void gsm_destroy_stuff(struct ast_trans_pvt *pvt) | ||||
|   | ||||
| @@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/translate.h" | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/utils.h" | ||||
| #include "asterisk/linkedlists.h" | ||||
|  | ||||
| #ifdef ILBC_WEBRTC | ||||
| #include <ilbc.h> | ||||
| @@ -150,31 +151,40 @@ static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | ||||
| static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt) | ||||
| { | ||||
| 	struct ilbc_coder_pvt *tmp = pvt->pvt; | ||||
| 	int datalen = 0; | ||||
| 	int samples = 0; | ||||
| 	struct ast_frame *result = NULL; | ||||
| 	struct ast_frame *last = NULL; | ||||
| 	int samples = 0; /* output samples */ | ||||
|  | ||||
| 	/* We can't work on anything less than a frame in size */ | ||||
| 	if (pvt->samples < ILBC_SAMPLES) | ||||
| 		return NULL; | ||||
| 	while (pvt->samples >= ILBC_SAMPLES) { | ||||
| 		struct ast_frame *current; | ||||
| 		ilbc_block tmpf[ILBC_SAMPLES]; | ||||
| 		int i; | ||||
|  | ||||
| 		/* Encode a frame of data */ | ||||
| 		for (i = 0 ; i < ILBC_SAMPLES ; i++) | ||||
| 			tmpf[i] = tmp->buf[samples + i]; | ||||
| 		iLBC_encode( (ilbc_bytes*)pvt->outbuf.BUF_TYPE + datalen, tmpf, &tmp->enc); | ||||
| 		iLBC_encode((ilbc_bytes *) pvt->outbuf.BUF_TYPE, tmpf, &tmp->enc); | ||||
|  | ||||
| 		datalen += ILBC_FRAME_LEN; | ||||
| 		samples += ILBC_SAMPLES; | ||||
| 		pvt->samples -= ILBC_SAMPLES; | ||||
|  | ||||
| 		current = ast_trans_frameout(pvt, ILBC_FRAME_LEN, ILBC_SAMPLES); | ||||
| 		if (!current) { | ||||
| 			continue; | ||||
| 		} else if (last) { | ||||
| 			AST_LIST_NEXT(last, frame_list) = current; | ||||
| 		} else { | ||||
| 			result = current; | ||||
| 		} | ||||
| 		last = current; | ||||
| 	} | ||||
|  | ||||
| 	/* Move the data at the end of the buffer to the front */ | ||||
| 	if (pvt->samples) | ||||
| 	if (samples) { | ||||
| 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | ||||
| 	} | ||||
|  | ||||
| 	return ast_trans_frameout(pvt, datalen, samples); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static struct ast_translator ilbctolin = { | ||||
|   | ||||
| @@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/config.h" | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/utils.h" | ||||
| #include "asterisk/linkedlists.h" | ||||
|  | ||||
| #include "lpc10/lpc10.h" | ||||
|  | ||||
| @@ -160,31 +161,45 @@ static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | ||||
| static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt) | ||||
| { | ||||
| 	struct lpc10_coder_pvt *tmp = pvt->pvt; | ||||
| 	int x; | ||||
| 	int datalen = 0;	/* output frame */ | ||||
| 	struct ast_frame *result = NULL; | ||||
| 	struct ast_frame *last = NULL; | ||||
| 	int samples = 0; /* output samples */ | ||||
|  | ||||
| 	while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) { | ||||
| 		struct ast_frame *current; | ||||
| 		float tmpbuf[LPC10_SAMPLES_PER_FRAME]; | ||||
| 		INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];	/* XXX what ??? */ | ||||
| 	/* We can't work on anything less than a frame in size */ | ||||
| 	if (pvt->samples < LPC10_SAMPLES_PER_FRAME) | ||||
| 		return NULL; | ||||
| 	while (pvt->samples >=  LPC10_SAMPLES_PER_FRAME) { | ||||
| 		int x; | ||||
|  | ||||
| 		/* Encode a frame of data */ | ||||
| 		for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) | ||||
| 			tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0; | ||||
| 		lpc10_encode(tmpbuf, bits, tmp->lpc10.enc); | ||||
| 		build_bits(pvt->outbuf.uc + datalen, bits); | ||||
| 		datalen += LPC10_BYTES_IN_COMPRESSED_FRAME; | ||||
| 		build_bits(pvt->outbuf.uc, bits); | ||||
|  | ||||
| 		samples += LPC10_SAMPLES_PER_FRAME; | ||||
| 		pvt->samples -= LPC10_SAMPLES_PER_FRAME; | ||||
| 		/* Use one of the two left over bits to record if this is a 22 or 23 ms frame... | ||||
| 		   important for IAX use */ | ||||
| 		tmp->longer = 1 - tmp->longer; | ||||
|  | ||||
| 		current = ast_trans_frameout(pvt, LPC10_BYTES_IN_COMPRESSED_FRAME, LPC10_SAMPLES_PER_FRAME); | ||||
| 		if (!current) { | ||||
| 			continue; | ||||
| 		} else if (last) { | ||||
| 			AST_LIST_NEXT(last, frame_list) = current; | ||||
| 		} else { | ||||
| 			result = current; | ||||
| 		} | ||||
| 		last = current; | ||||
| 	} | ||||
|  | ||||
| 	/* Move the data at the end of the buffer to the front */ | ||||
| 	if (pvt->samples) | ||||
| 	if (samples) { | ||||
| 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | ||||
| 	return ast_trans_frameout(pvt, datalen, samples); | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -54,6 +54,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/config.h" | ||||
| #include "asterisk/utils.h" | ||||
| #include "asterisk/frame.h" | ||||
| #include "asterisk/linkedlists.h" | ||||
|  | ||||
| /* codec variables */ | ||||
| static int quality = 3; | ||||
| @@ -259,15 +261,16 @@ static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | ||||
| static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) | ||||
| { | ||||
| 	struct speex_coder_pvt *tmp = pvt->pvt; | ||||
| 	int is_speech=1; | ||||
| 	int datalen = 0;	/* output bytes */ | ||||
| 	struct ast_frame *result = NULL; | ||||
| 	struct ast_frame *last = NULL; | ||||
| 	int samples = 0; /* output samples */ | ||||
|  | ||||
| 	/* We can't work on anything less than a frame in size */ | ||||
| 	if (pvt->samples < tmp->framesize) | ||||
| 		return NULL; | ||||
| 	speex_bits_reset(&tmp->bits); | ||||
| 	while (pvt->samples >= tmp->framesize) { | ||||
| 		struct ast_frame *current; | ||||
| 		int is_speech = 1; | ||||
|  | ||||
| 		speex_bits_reset(&tmp->bits); | ||||
|  | ||||
| #ifdef _SPEEX_TYPES_H | ||||
| 		/* Preprocess audio */ | ||||
| 		if (preproc) | ||||
| @@ -293,18 +296,18 @@ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) | ||||
| #endif | ||||
| 		samples += tmp->framesize; | ||||
| 		pvt->samples -= tmp->framesize; | ||||
| 	} | ||||
|  | ||||
| 	/* Move the data at the end of the buffer to the front */ | ||||
| 	if (pvt->samples) | ||||
| 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | ||||
|  | ||||
| 		/* Use AST_FRAME_CNG to signify the start of any silence period */ | ||||
| 		if (is_speech) { | ||||
| 			int datalen = 0; /* output bytes */ | ||||
|  | ||||
| 			tmp->silent_state = 0; | ||||
| 	} else { | ||||
| 		if (tmp->silent_state) { | ||||
| 			return NULL; | ||||
| 			/* Terminate bit stream */ | ||||
| 			speex_bits_pack(&tmp->bits, 15, 5); | ||||
| 			datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size); | ||||
| 			current = ast_trans_frameout(pvt, datalen, tmp->framesize); | ||||
| 		} else if (tmp->silent_state) { | ||||
| 			current = NULL; | ||||
| 		} else { | ||||
| 			struct ast_frame frm = { | ||||
| 				.frametype = AST_FRAME_CNG, | ||||
| @@ -320,14 +323,25 @@ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) | ||||
| 			tmp->silent_state = 1; | ||||
|  | ||||
| 			/* XXX what now ? format etc... */ | ||||
| 			return ast_frisolate(&frm); | ||||
| 		} | ||||
| 			current = ast_frisolate(&frm); | ||||
| 		} | ||||
|  | ||||
| 	/* Terminate bit stream */ | ||||
| 	speex_bits_pack(&tmp->bits, 15, 5); | ||||
| 	datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size); | ||||
| 	return ast_trans_frameout(pvt, datalen, samples); | ||||
| 		if (!current) { | ||||
| 			continue; | ||||
| 		} else if (last) { | ||||
| 			AST_LIST_NEXT(last, frame_list) = current; | ||||
| 		} else { | ||||
| 			result = current; | ||||
| 		} | ||||
| 		last = current; | ||||
| 	} | ||||
|  | ||||
| 	/* Move the data at the end of the buffer to the front */ | ||||
| 	if (samples) { | ||||
| 		memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static void speextolin_destroy(struct ast_trans_pvt *arg) | ||||
|   | ||||
| @@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/cli.h" | ||||
| #include "asterisk/term.h" | ||||
| #include "asterisk/format.h" | ||||
| #include "asterisk/linkedlists.h" | ||||
|  | ||||
| /*! \todo | ||||
|  * TODO: sample frames for each supported input format. | ||||
| @@ -547,7 +548,12 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, | ||||
| 	} | ||||
| 	delivery = f->delivery; | ||||
| 	for (out = f; out && p ; p = p->next) { | ||||
| 		framein(p, out); | ||||
| 		struct ast_frame *current = out; | ||||
|  | ||||
| 		do { | ||||
| 			framein(p, current); | ||||
| 			current = AST_LIST_NEXT(current, frame_list); | ||||
| 		} while (current); | ||||
| 		if (out != f) { | ||||
| 			ast_frfree(out); | ||||
| 		} | ||||
| @@ -556,22 +562,33 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, | ||||
| 	if (out) { | ||||
| 		/* we have a frame, play with times */ | ||||
| 		if (!ast_tvzero(delivery)) { | ||||
| 			struct ast_frame *current = out; | ||||
|  | ||||
| 			do { | ||||
| 				/* Regenerate prediction after a discontinuity */ | ||||
| 				if (ast_tvzero(path->nextout)) { | ||||
| 					path->nextout = ast_tvnow(); | ||||
| 				} | ||||
|  | ||||
| 				/* Use next predicted outgoing timestamp */ | ||||
| 			out->delivery = path->nextout; | ||||
| 				current->delivery = path->nextout; | ||||
|  | ||||
| 				/* Invalidate prediction if we're entering a silence period */ | ||||
| 				if (current->frametype == AST_FRAME_CNG) { | ||||
| 					path->nextout = ast_tv(0, 0); | ||||
| 				/* Predict next outgoing timestamp from samples in this | ||||
| 				   frame. */ | ||||
| 				} else { | ||||
| 					path->nextout = ast_tvadd(path->nextout, ast_samp2tv( | ||||
| 				 out->samples, ast_format_get_sample_rate(out->subclass.format))); | ||||
| 			if (f->samples != out->samples && ast_test_flag(out, AST_FRFLAG_HAS_TIMING_INFO)) { | ||||
| 				ast_debug(4, "Sample size different %d vs %d\n", f->samples, out->samples); | ||||
| 				ast_clear_flag(out, AST_FRFLAG_HAS_TIMING_INFO); | ||||
| 						current->samples, ast_format_get_sample_rate(current->subclass.format))); | ||||
| 				} | ||||
|  | ||||
| 				if (f->samples != current->samples && ast_test_flag(current, AST_FRFLAG_HAS_TIMING_INFO)) { | ||||
| 					ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples); | ||||
| 					ast_clear_flag(current, AST_FRFLAG_HAS_TIMING_INFO); | ||||
| 				} | ||||
| 				current = AST_LIST_NEXT(current, frame_list); | ||||
| 			} while (current); | ||||
| 		} else { | ||||
| 			out->delivery = ast_tv(0, 0); | ||||
| 			ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); | ||||
| @@ -580,12 +597,12 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, | ||||
| 				out->len = len; | ||||
| 				out->seqno = seqno; | ||||
| 			} | ||||
| 		} | ||||
| 			/* Invalidate prediction if we're entering a silence period */ | ||||
| 			if (out->frametype == AST_FRAME_CNG) { | ||||
| 				path->nextout = ast_tv(0, 0); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if (consume) { | ||||
| 		ast_frfree(f); | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user