diff options
author | Alexander Traud <pabstraud@compuserve.com> | 2015-08-28 22:42:23 +0200 |
---|---|---|
committer | Alexander Traud <pabstraud@compuserve.com> | 2015-09-17 10:01:48 -0500 |
commit | b88c54fa4bd537bde46519abb95e30a5f96673ac (patch) | |
tree | 84318723a2ab5ce06f0880b3f0cbb144f8e8e3cd /codecs/codec_speex.c | |
parent | 5c713fdf18ffa934e0cac8ddb29e4ad95a68200b (diff) |
translate: Fix transcoding while different in frame size.
When Asterisk translates between codecs, each with a different frame size (for
example between iLBC 30 and Speex-WB), too large frames were created by
ast_trans_frameout. Now, ast_trans_frameout is called with the correct frame
length, creating several frames when necessary. Affects all transcoding modules
which used ast_trans_frameout: GSM, iLBC, LPC10, and Speex.
ASTERISK-25353 #close
Change-Id: I2e229569d73191d66a4e43fef35432db24000212
Diffstat (limited to 'codecs/codec_speex.c')
-rw-r--r-- | codecs/codec_speex.c | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c index c91070d9e..c9adceb2f 100644 --- a/codecs/codec_speex.c +++ b/codecs/codec_speex.c @@ -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 */ - int samples = 0; /* output samples */ + 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) { - tmp->silent_state = 0; - } else { - if (tmp->silent_state) { - return NULL; + /* Use AST_FRAME_CNG to signify the start of any silence period */ + if (is_speech) { + int datalen = 0; /* output bytes */ + + tmp->silent_state = 0; + /* 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); } + + 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); } - /* 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); + return result; } static void speextolin_destroy(struct ast_trans_pvt *arg) |