From cbc680adc0875bedd46977b878f77a9e8cee3d88 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 14 Jan 2009 19:44:14 +0000 Subject: [PATCH] fix buffering issue in mod_shout/core git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11200 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/formats/mod_shout/mod_shout.c | 40 ++++++++++++++++++--------- src/switch_core_file.c | 26 ++++++++++------- src/switch_ivr_play_say.c | 1 + 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index 63af4b55c0..32df81e939 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -116,6 +116,12 @@ struct shout_context { int lame_ready; int eof; int channels; + int16_t *l; + switch_size_t llen; + int16_t *r; + switch_size_t rlen; + unsigned char *mp3buf; + switch_size_t mp3buflen; }; typedef struct shout_context shout_context_t; @@ -903,8 +909,7 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data, static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data, size_t *len) { shout_context_t *context; - unsigned char mp3buf[8192] = ""; - int rlen; + int rlen = 0; int16_t *audio = data; int nsamples = *len; @@ -954,23 +959,32 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data context->lame_ready = 1; } + if (context->mp3buflen < nsamples * 4) { + context->mp3buflen = nsamples * 4; + context->mp3buf = switch_core_alloc(context->memory_pool, context->mp3buflen); + } + if (handle->channels == 2) { - int16_t l[4096] = { 0 }; - int16_t r[4096] = { 0 }; int i, j = 0; - - for (i = 0; i < nsamples; i++) { - l[i] = audio[j++]; - r[i] = audio[j++]; + + if (context->llen < nsamples) { + context->l = switch_core_alloc(context->memory_pool, nsamples * 2); + context->r = switch_core_alloc(context->memory_pool, nsamples * 2); + context->llen = context->rlen = nsamples; } - - if ((rlen = lame_encode_buffer(context->gfp, l, r, nsamples, mp3buf, sizeof(mp3buf))) < 0) { + + for (i = 0; i < nsamples; i++) { + context->l[i] = audio[j++]; + context->r[i] = audio[j++]; + } + + if ((rlen = lame_encode_buffer(context->gfp, context->l, context->r, nsamples, context->mp3buf, context->mp3buflen)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); return SWITCH_STATUS_FALSE; } } else if (handle->channels == 1) { - if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, mp3buf, sizeof(mp3buf))) < 0) { + if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, context->mp3buf, context->mp3buflen)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); return SWITCH_STATUS_FALSE; } @@ -979,7 +993,7 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data } if (rlen) { - int ret = fwrite(mp3buf, 1, rlen, context->fp); + int ret = fwrite(context->mp3buf, 1, rlen, context->fp); if (ret < 0) { return SWITCH_STATUS_FALSE; } @@ -1445,7 +1459,7 @@ static switch_status_t load_config(void) for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); - + if (!strcmp(var, "decoder")) { switch_set_string(globals.decoder, val); } else if (!strcmp(var, "volume")) { diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 8a18b534bf..f11b0a8df8 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -119,7 +119,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, if (fh->pre_buffer_datalen) { //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Prebuffering %d bytes\n", (int)fh->pre_buffer_datalen); - switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen, fh->pre_buffer_datalen / 2, 0); + switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen * fh->channels, fh->pre_buffer_datalen * fh->channels / 2, 0); fh->pre_buffer_data = switch_core_alloc(fh->memory_pool, fh->pre_buffer_datalen); } @@ -248,16 +248,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) { if (!fh->resampler) { if (switch_resample_create(&fh->resampler, - fh->native_rate, orig_len, fh->samplerate, (uint32_t) orig_len, fh->memory_pool) != SWITCH_STATUS_SUCCESS) { + fh->native_rate, + orig_len * fh->channels, + fh->samplerate, + (uint32_t) orig_len *fh->channels, + fh->memory_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n"); return SWITCH_STATUS_GENERR; } } - fh->resampler->from_len = switch_short_to_float(data, fh->resampler->from, (int) *len); + fh->resampler->from_len = switch_short_to_float(data, fh->resampler->from, (int) *len * fh->channels); fh->resampler->to_len = switch_resample_process(fh->resampler, fh->resampler->from, fh->resampler->from_len, fh->resampler->to, fh->resampler->to_size, 0); - if (fh->resampler->to_len > orig_len) { + if (fh->resampler->to_len > orig_len * fh->channels) { if (!fh->dbuf) { fh->dbuflen = fh->resampler->to_len * 2; fh->dbuf = switch_core_alloc(fh->memory_pool, fh->dbuflen); @@ -269,7 +273,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, switch_float_to_short(fh->resampler->to, data, fh->resampler->to_len); } - *len = fh->resampler->to_len; + *len = fh->resampler->to_len / fh->channels; } @@ -282,13 +286,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, switch_size_t rlen, blen; switch_status_t status = SWITCH_STATUS_SUCCESS; int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE); - - switch_buffer_write(fh->pre_buffer, data, asis ? *len : *len * 2); + + switch_buffer_write(fh->pre_buffer, data, (asis ? *len : *len * 2) * fh->channels); rlen = switch_buffer_inuse(fh->pre_buffer); if (rlen >= fh->pre_buffer_datalen) { blen = switch_buffer_read(fh->pre_buffer, fh->pre_buffer_data, fh->pre_buffer_datalen); if (!asis) blen /= 2; + if (fh->channels) blen /= fh->channels; if ((status = fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen)) != SWITCH_STATUS_SUCCESS) { *len = 0; } @@ -354,9 +359,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) return SWITCH_STATUS_FALSE; } - switch_clear_flag(fh, SWITCH_FILE_OPEN); - status = fh->file_interface->file_close(fh); - if (fh->buffer) { switch_buffer_destroy(&fh->buffer); } @@ -369,6 +371,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) while((rlen = switch_buffer_inuse(fh->pre_buffer))) { blen = switch_buffer_read(fh->pre_buffer, fh->pre_buffer_data, fh->pre_buffer_datalen); if (asis) blen /= 2; + if (fh->channels) blen /= fh->channels; if (fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen) != SWITCH_STATUS_SUCCESS) { break; } @@ -378,6 +381,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) switch_buffer_destroy(&fh->pre_buffer); } + switch_clear_flag(fh, SWITCH_FILE_OPEN); + status = fh->file_interface->file_close(fh); + switch_resample_destroy(&fh->resampler); UNPROTECT_INTERFACE(fh->file_interface); diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index a41f7c0326..11e0972a91 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -420,6 +420,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se } } + fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN; if (switch_core_file_open(fh, file,