]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix buffering issue in mod_shout/core
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 14 Jan 2009 19:44:14 +0000 (19:44 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 14 Jan 2009 19:44:14 +0000 (19:44 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11200 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/formats/mod_shout/mod_shout.c
src/switch_core_file.c
src/switch_ivr_play_say.c

index 63af4b55c0c5ef53c9a5d36a9b8cd80fbaad4963..32df81e939b2b50fc426e94e092dd6d41b27f8eb 100644 (file)
@@ -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;
-
+               
+               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;
+               }
+               
                for (i = 0; i < nsamples; i++) {
-                       l[i] = audio[j++];
-                       r[i] = audio[j++];
+                       context->l[i] = audio[j++];
+                       context->r[i] = audio[j++];
                }
-
-               if ((rlen = lame_encode_buffer(context->gfp, l, r, nsamples, mp3buf, sizeof(mp3buf))) < 0) {
+               
+               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")) {
index 8a18b534bff997d3514e23c3d1dd83eac6782ecd..f11b0a8df8ce3eed746f6e6c89ddc94690976204 100644 (file)
@@ -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);
index a41f7c0326f84ff3fc183f1a14ed34b537f1168f..11e0972a91a04baf1f5e345e2da8bb4463d9b5de 100644 (file)
@@ -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,