From 56cb227eb7bc81f9c3341de31563fd4f5429711e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Apr 2006 19:04:30 +0000 Subject: [PATCH] add ilbc git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1199 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/codecs/mod_ilbc/mod_ilbc.c | 161 ++++++++++++++-------- src/mod/endpoints/mod_exosip/mod_exosip.c | 19 ++- src/mod/endpoints/mod_iax/mod_iax.c | 2 +- src/switch_buffer.c | 12 +- src/switch_core.c | 7 +- src/switch_ivr.c | 6 +- 6 files changed, 133 insertions(+), 74 deletions(-) diff --git a/src/mod/codecs/mod_ilbc/mod_ilbc.c b/src/mod/codecs/mod_ilbc/mod_ilbc.c index dadbd4deac..006683535d 100644 --- a/src/mod/codecs/mod_ilbc/mod_ilbc.c +++ b/src/mod/codecs/mod_ilbc/mod_ilbc.c @@ -32,12 +32,16 @@ #include "switch.h" #include "iLBC_encode.h" #include "iLBC_decode.h" +#include "iLBC_define.h" static const char modname[] = "mod_ilbc"; struct ilbc_context { iLBC_Enc_Inst_t encoder; iLBC_Dec_Inst_t decoder; + uint8_t ms; + uint16_t bytes; + uint16_t dbytes; }; static switch_status switch_ilbc_init(switch_codec *codec, switch_codec_flag flags, @@ -45,6 +49,13 @@ static switch_status switch_ilbc_init(switch_codec *codec, switch_codec_flag fla { struct ilbc_context *context; int encoding, decoding; + uint8_t ms = codec->implementation->microseconds_per_frame / 1000; + + + if (ms != 20 && ms != 30) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid speed! (I should never happen)\n"); + return SWITCH_STATUS_FALSE; + } encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); @@ -53,10 +64,21 @@ static switch_status switch_ilbc_init(switch_codec *codec, switch_codec_flag fla return SWITCH_STATUS_FALSE; } else { context = switch_core_alloc(codec->memory_pool, sizeof(*context)); - if (encoding) - initEncode(&context->encoder, 30); - if (decoding) - initDecode(&context->decoder, 30, 0); + context->ms = ms; + if (context->ms == 20) { + context->bytes = NO_OF_BYTES_20MS; + context->dbytes = 320; + } else { + context->bytes = NO_OF_BYTES_30MS; + context->dbytes = 480; + } + + if (encoding) { + initEncode(&context->encoder, context->ms); + } + if (decoding) { + initDecode(&context->decoder, context->ms, 1); + } } codec->private_info = context; @@ -70,35 +92,38 @@ static switch_status switch_ilbc_destroy(switch_codec *codec) return SWITCH_STATUS_SUCCESS; } -static switch_status switch_ilbc_encode(switch_codec *codec, - switch_codec *other_codec, - void *decoded_data, - size_t decoded_data_len, - int decoded_rate, - void *encoded_data, - - size_t *encoded_data_len, - int *encoded_rate, - unsigned int *flag) +static switch_status switch_ilbc_encode(switch_codec *codec, + switch_codec *other_codec, + void *decoded_data, + uint32_t decoded_data_len, + uint32_t decoded_rate, + void *encoded_data, + uint32_t *encoded_data_len, + uint32_t *encoded_rate, + unsigned int *flag) { struct ilbc_context *context = codec->private_info; - int cbret = 0; if (!context) { return SWITCH_STATUS_FALSE; } - if (decoded_data_len % 320 == 0) { + if (decoded_data_len % context->dbytes == 0) { unsigned int new_len = 0; - ilbc_signal * ddp = decoded_data; - ilbc_byte * edp = encoded_data; - int x; - int loops = (int) decoded_data_len / 320; + unsigned char *edp = encoded_data; + short *ddp = decoded_data; + int x, y; + int loops = (int) decoded_data_len / context->dbytes; + float buf[240]; + for (x = 0; x < loops && new_len < *encoded_data_len; x++) { - iLBC_encode(context->encoder, ddp, edp); - edp += 33; - ddp += 160; - new_len += 33; + for(y = 0; y < context->dbytes / sizeof(short) ; y++) { + buf[y] = ddp[y]; + } + iLBC_encode(edp, buf, &context->encoder); + edp += context->bytes; + ddp += context->dbytes; + new_len += context->bytes; } if (new_len <= *encoded_data_len) { *encoded_data_len = new_len; @@ -110,17 +135,15 @@ static switch_status switch_ilbc_encode(switch_codec *codec, return SWITCH_STATUS_SUCCESS; } -static switch_status switch_ilbc_decode(switch_codec *codec, - switch_codec *other_codec, +static switch_status switch_ilbc_decode(switch_codec *codec, + switch_codec *other_codec, void *encoded_data, - - size_t encoded_data_len, - int encoded_rate, + uint32_t encoded_data_len, + uint32_t encoded_rate, void *decoded_data, - - size_t *decoded_data_len, - int *decoded_rate, - unsigned int *flag) + uint32_t *decoded_data_len, + uint32_t *decoded_rate, + unsigned int *flag) { struct ilbc_context *context = codec->private_info; @@ -128,18 +151,23 @@ static switch_status switch_ilbc_decode(switch_codec *codec, return SWITCH_STATUS_FALSE; } - if (encoded_data_len % 33 == 0) { - int loops = (int) encoded_data_len / 33; - ilbc_byte * edp = encoded_data; - ilbc_signal * ddp = decoded_data; - int x; + if (encoded_data_len % context->bytes == 0) { + int loops = (int) encoded_data_len / context->bytes; + unsigned char *edp = encoded_data; + short *ddp = decoded_data; + int x,y; unsigned int new_len = 0; + float buf[240]; + for (x = 0; x < loops && new_len < *decoded_data_len; x++) { - iLBC_decode(context->decoder, edp, ddp); - ddp += 160; - edp += 33; - new_len += 320; + iLBC_decode(buf, edp, &context->decoder, 1); + for(y = 0; y < context->dbytes / sizeof(short) ; y++) { + ddp[y] = buf[y]; + } + ddp += context->dbytes / sizeof(short); + edp += context->bytes; + new_len += context->dbytes; } if (new_len <= *decoded_data_len) { *decoded_data_len = new_len; @@ -156,29 +184,46 @@ static switch_status switch_ilbc_decode(switch_codec *codec, /* Registration */ -static const switch_codec_implementation ilbc_8k_implementation = { +static const switch_codec_implementation ilbc_8k_30ms_implementation = { /*.samples_per_second */ 8000, - /*.bits_per_second */ 13200, - /*.microseconds_per_frame */ 20000, - /*.samples_per_frame */ 160, - /*.bytes_per_frame */ 320, - /*.encoded_bytes_per_frame */ 33, - /*.number_of_channels */ 1, - /*.pref_frames_per_packet */ 1, - /*.max_frames_per_packet */ 1, - /*.init */ switch_ilbc_init, - /*.encode */ switch_ilbc_encode, - /*.decode */ switch_ilbc_decode, - /*.destroy */ switch_ilbc_destroy, + /*.bits_per_second */ NO_OF_BYTES_30MS*8*8000/BLOCKL_30MS, + /*.microseconds_per_frame */ 30000, + /*.samples_per_frame */ 240, + /*.bytes_per_frame */ 480, + /*.encoded_bytes_per_frame */ NO_OF_BYTES_30MS, + /*.number_of_channels */ 1, + /*.pref_frames_per_packet */ 1, + /*.max_frames_per_packet */ 1, + /*.init */ switch_ilbc_init, + /*.encode */ switch_ilbc_encode, + /*.decode */ switch_ilbc_decode, + /*.destroy */ switch_ilbc_destroy +}; + +static const switch_codec_implementation ilbc_8k_20ms_implementation = { + /*.samples_per_second */ 8000, + /*.bits_per_second */ NO_OF_BYTES_20MS*8*8000/BLOCKL_20MS, + /*.microseconds_per_frame */ 20000, + /*.samples_per_frame */ 160, + /*.bytes_per_frame */ 320, + /*.encoded_bytes_per_frame */ NO_OF_BYTES_20MS, + /*.number_of_channels */ 1, + /*.pref_frames_per_packet */ 1, + /*.max_frames_per_packet */ 1, + /*.init */ switch_ilbc_init, + /*.encode */ switch_ilbc_encode, + /*.decode */ switch_ilbc_decode, + /*.destroy */ switch_ilbc_destroy, + /*.next */ &ilbc_8k_30ms_implementation }; static const switch_codec_interface ilbc_codec_interface = { /*.interface_name */ "ilbc", /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, - /*.ianacode */ 3, - /*.iananame */ "ilbc", - /*.implementations */ &ilbc_8k_implementation, + /*.ianacode */ 97, + /*.iananame */ "iLBC", + /*.implementations */ &ilbc_8k_20ms_implementation, }; diff --git a/src/mod/endpoints/mod_exosip/mod_exosip.c b/src/mod/endpoints/mod_exosip/mod_exosip.c index d17172e9cb..d070cbe60b 100644 --- a/src/mod/endpoints/mod_exosip/mod_exosip.c +++ b/src/mod/endpoints/mod_exosip/mod_exosip.c @@ -1283,11 +1283,15 @@ static switch_status exosip_create_call(eXosip_event_t * event) { int rate = atoi(drate); - + int ms = globals.codec_ms; + if (!strcasecmp(dname, "ilbc")) { + ms = 30; + } + if (switch_core_codec_init(&tech_pvt->read_codec, dname, rate, - globals.codec_ms, + ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { @@ -1298,7 +1302,7 @@ static switch_status exosip_create_call(eXosip_event_t * event) if (switch_core_codec_init(&tech_pvt->write_codec, dname, rate, - globals.codec_ms, + ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { @@ -1453,12 +1457,15 @@ static void handle_answer(eXosip_event_t * event) { int rate = atoi(drate); - + int ms = globals.codec_ms; + if (!strcasecmp(dname, "ilbc")) { + ms = 30; + } if (switch_core_codec_init(&tech_pvt->read_codec, dname, rate, - globals.codec_ms, + ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { @@ -1469,7 +1476,7 @@ static void handle_answer(eXosip_event_t * event) if (switch_core_codec_init(&tech_pvt->write_codec, dname, rate, - globals.codec_ms, + ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, diff --git a/src/mod/endpoints/mod_iax/mod_iax.c b/src/mod/endpoints/mod_iax/mod_iax.c index 0c26b64f49..29dcc54a8d 100644 --- a/src/mod/endpoints/mod_iax/mod_iax.c +++ b/src/mod/endpoints/mod_iax/mod_iax.c @@ -129,7 +129,7 @@ static struct ast_iana AST_IANA[] = { {AST_FORMAT_G723_1, 4, "g723.1"}, {AST_FORMAT_LPC10, 7, "lpc10"}, {AST_FORMAT_G729A, 18, "g729"}, {AST_FORMAT_SPEEX, 98, "speex"}, -{AST_FORMAT_ILBC, 999, "ilbc"}, +{AST_FORMAT_ILBC, 102, "ilbc"}, {AST_FORMAT_MAX_AUDIO, 999, ""}, {AST_FORMAT_JPEG, 999, ""}, {AST_FORMAT_PNG, 999, ""}, diff --git a/src/switch_buffer.c b/src/switch_buffer.c index 3541cab2d3..6882b1f957 100644 --- a/src/switch_buffer.c +++ b/src/switch_buffer.c @@ -31,10 +31,13 @@ */ #include +static uint32_t buffer_id = 0; + struct switch_buffer { unsigned char *data; switch_size_t used; switch_size_t datalen; + uint32_t id; }; SWITCH_DECLARE(switch_status) switch_buffer_create(switch_memory_pool *pool, switch_buffer **buffer, switch_size_t max_len) @@ -44,6 +47,7 @@ SWITCH_DECLARE(switch_status) switch_buffer_create(switch_memory_pool *pool, swi if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer))) != 0 && (new_buffer->data = switch_core_alloc(pool, max_len)) != 0) { new_buffer->datalen = max_len; + new_buffer->id = buffer_id++; *buffer = new_buffer; return SWITCH_STATUS_SUCCESS; } @@ -115,7 +119,7 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_read(switch_buffer *buffer, void *da memcpy(data, buffer->data, reading); memmove(buffer->data, buffer->data + reading, buffer->datalen - reading); buffer->used -= reading; - //printf("o %d = %d\n", reading, buffer->used); + //if (buffer->id == 3) printf("%u o %d = %d\n", buffer->id, (uint32_t)reading, (uint32_t)buffer->used); return reading; } @@ -126,16 +130,16 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_write(switch_buffer *buffer, void *d assert(buffer != NULL); assert(data != NULL); assert(buffer->data != NULL); - + freespace = buffer->datalen - buffer->used; - if (freespace < datalen) { return 0; } else { memcpy(buffer->data + buffer->used, data, datalen); buffer->used += datalen; } - //printf("i %d = %d\n", datalen, buffer->used); + //if (buffer->id == 3) printf("%u i %d = %d\n", buffer->id, (uint32_t)datalen, (uint32_t)buffer->used); + return buffer->used; } diff --git a/src/switch_core.c b/src/switch_core.c index 9ffb44b2b7..03d5d3d991 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1265,7 +1265,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio } } if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write Buffer Failed!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen); return SWITCH_STATUS_MEMERR; } } @@ -1374,9 +1374,12 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio write_frame->datalen = session->read_resampler->to_len * 2; write_frame->rate = session->read_resampler->to_rate; } - return perform_write(session, write_frame, timeout, io_flag, stream_id); + if ((status = perform_write(session, write_frame, timeout, io_flag, stream_id)) != SWITCH_STATUS_SUCCESS) { + break; + } } } + return status; } } } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 771eef05ee..b0bab90501 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -266,6 +266,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session, int stream_id; switch_status status = SWITCH_STATUS_SUCCESS; switch_file_handle lfh; + switch_codec *read_codec = switch_core_session_get_read_codec(session); if (!fh) { fh = &lfh; @@ -290,10 +291,9 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "OPEN FILE %s %uhz %u channels\n", file, fh->samplerate, fh->channels); - interval = 20; - samples = ((fh->samplerate / 50) * fh->channels); + interval = read_codec->implementation->microseconds_per_frame / 1000; + samples = read_codec->implementation->bytes_per_frame / 2; len = samples * 2; - codec_name = "L16"; if (switch_core_codec_init(&codec,