[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