Index: audio/gstsbcdec.c =================================================================== RCS file: /cvsroot/bluez/utils/audio/gstsbcdec.c,v retrieving revision 1.5 diff -u -r1.5 gstsbcdec.c --- audio/gstsbcdec.c 27 Aug 2007 14:10:00 -0000 1.5 +++ audio/gstsbcdec.c 12 Nov 2007 17:47:28 -0000 @@ -58,10 +58,11 @@ { GstSbcDec *dec = GST_SBC_DEC(gst_pad_get_parent(pad)); GstFlowReturn res = GST_FLOW_OK; - guint size, offset = 0; + guint size, codesize, offset = 0; guint8 *data; GstClockTime timestamp; + codesize = sbc_get_codesize(&dec->sbc); timestamp = GST_BUFFER_TIMESTAMP(buffer); if (dec->buffer) { @@ -82,10 +83,6 @@ GstCaps *caps, *temp; int consumed; - consumed = sbc_decode(&dec->sbc, data + offset, size - offset); - if (consumed <= 0) - break; - caps = gst_caps_new_simple("audio/x-raw-int", "rate", G_TYPE_INT, dec->sbc.rate, "channels", G_TYPE_INT, dec->sbc.channels, @@ -100,14 +97,20 @@ res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad, GST_BUFFER_OFFSET_NONE, - dec->sbc.len, temp, &output); + codesize, temp, &output); gst_caps_unref(temp); if (res != GST_FLOW_OK) goto done; - memcpy(GST_BUFFER_DATA(output), dec->sbc.data, dec->sbc.len); + consumed = sbc_decode(&dec->sbc, data + offset, size - offset, + GST_BUFFER_DATA(output), codesize, + NULL); + if (consumed <= 0) + break; + + GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer); res = gst_pad_push(dec->srcpad, output); if (res != GST_FLOW_OK) Index: audio/gstsbcenc.c =================================================================== RCS file: /cvsroot/bluez/utils/audio/gstsbcenc.c,v retrieving revision 1.9 diff -u -r1.9 gstsbcenc.c --- audio/gstsbcenc.c 1 Nov 2007 19:45:00 -0000 1.9 +++ audio/gstsbcenc.c 12 Nov 2007 17:47:28 -0000 @@ -134,10 +134,11 @@ enc->sbc.rate = rate; enc->sbc.channels = channels; - if (enc->mode == 0) - enc->sbc.joint = CFG_MODE_JOINT_STEREO; - else - enc->sbc.joint = enc->mode; + if (enc->mode == CFG_MODE_AUTO) + enc->mode = CFG_MODE_JOINT_STEREO; + + if (enc->mode == CFG_MODE_MONO || enc->mode == CFG_MODE_JOINT_STEREO) + enc->sbc.joint = 1; enc->sbc.blocks = enc->blocks; enc->sbc.subbands = enc->subbands; @@ -247,8 +248,10 @@ GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad)); GstAdapter *adapter = enc->adapter; GstFlowReturn res = GST_FLOW_OK; - gint codesize = enc->sbc.subbands * enc->sbc.blocks * enc->sbc.channels * 2; + gint codesize, frame_len; + codesize = sbc_get_codesize(&enc->sbc); + frame_len = sbc_get_frame_length(&enc->sbc); gst_adapter_push(adapter, buffer); while (gst_adapter_available(adapter) >= codesize && res == GST_FLOW_OK) { @@ -257,20 +260,22 @@ const guint8 *data; int consumed; + caps = GST_PAD_CAPS(enc->srcpad); + + res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad, + GST_BUFFER_OFFSET_NONE, + frame_len, caps, &output); + data = gst_adapter_peek(adapter, codesize); - consumed = sbc_encode(&enc->sbc, (gpointer) data, codesize); + consumed = sbc_encode(&enc->sbc, (gpointer) data, codesize, + GST_BUFFER_DATA(output), frame_len, + NULL); if (consumed <= 0) { GST_ERROR ("comsumed < 0, codesize: %d", codesize); break; } gst_adapter_flush(adapter, consumed); - caps = GST_PAD_CAPS(enc->srcpad); - - res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad, - GST_BUFFER_OFFSET_NONE, - enc->sbc.len, caps, &output); - if (res != GST_FLOW_OK) goto done; @@ -282,7 +287,6 @@ goto done; } - memcpy(GST_BUFFER_DATA(output), enc->sbc.data, enc->sbc.len); GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer); res = gst_pad_push(enc->srcpad, output); Index: audio/pcm_bluetooth.c =================================================================== RCS file: /cvsroot/bluez/utils/audio/pcm_bluetooth.c,v retrieving revision 1.80 diff -u -r1.80 pcm_bluetooth.c --- audio/pcm_bluetooth.c 9 Nov 2007 13:09:09 -0000 1.80 +++ audio/pcm_bluetooth.c 12 Nov 2007 17:47:28 -0000 @@ -666,7 +666,7 @@ struct bluetooth_a2dp *a2dp = &data->a2dp; snd_pcm_sframes_t ret = 0; snd_pcm_uframes_t frames_to_read, frames_left = size; - int frame_size, encoded; + int frame_size, encoded, written; uint8_t *buff; DBG("areas->step=%u areas->first=%u offset=%lu size=%lu", @@ -728,30 +728,30 @@ } /* Enough data to encode (sbc wants 1k blocks) */ - encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize); + encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize, + a2dp->buffer, sizeof(a2dp->buffer), + &written); if (encoded <= 0) { DBG("Encoding error %d", encoded); goto done; } data->count -= encoded; + a2dp->count += written; + a2dp->frame_count++; + a2dp->samples += encoded / frame_size; + a2dp->nsamples += encoded / frame_size; + + DBG("encoded=%d written=%d count=%d", encoded, + written, a2dp->count); - DBG("encoded=%d a2dp.sbc.len=%d count=%d", encoded, - a2dp->sbc.len, a2dp->count); - - /* Send previously encoded buffer */ - if (a2dp->count + a2dp->sbc.len >= data->cfg.pkt_len) { + /* No space left for another frame then send */ + if (a2dp->count + written >= data->cfg.pkt_len) { avdtp_write(data); DBG("sending packet %d, count %d, pkt_len %u", c, old_count, data->cfg.pkt_len); } - memcpy(a2dp->buffer + a2dp->count, a2dp->sbc.data, a2dp->sbc.len); - a2dp->count += a2dp->sbc.len; - a2dp->frame_count++; - a2dp->samples += encoded / frame_size; - a2dp->nsamples += encoded / frame_size; - ret += frames_to_read; frames_left -= frames_to_read; } Index: sbc/sbc.c =================================================================== RCS file: /cvsroot/bluez/utils/sbc/sbc.c,v retrieving revision 1.21 diff -u -r1.21 sbc.c --- sbc/sbc.c 5 Nov 2007 15:54:50 -0000 1.21 +++ sbc/sbc.c 12 Nov 2007 17:47:28 -0000 @@ -95,6 +95,8 @@ } allocation_method; uint8_t subbands; uint8_t bitpool; + uint8_t codesize; + uint8_t length; /* bit number x set means joint stereo has been used in subband x */ uint8_t join; @@ -1230,23 +1232,24 @@ return 0; } -int sbc_parse(sbc_t *sbc, void *data, int count) +int sbc_parse(sbc_t *sbc, void *input, int input_len) { - return sbc_decode(sbc, data, count); + return sbc_decode(sbc, input, input_len, NULL, 0, NULL); } -int sbc_decode(sbc_t *sbc, void *data, int count) +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; - framelen = sbc_unpack_frame(data, &priv->frame, count); + framelen = sbc_unpack_frame(input, &priv->frame, input_len); if (!priv->init) { sbc_decoder_init(&priv->dec_state, &priv->frame); @@ -1257,26 +1260,23 @@ sbc->subbands = priv->frame.subbands; sbc->blocks = priv->frame.blocks; sbc->bitpool = priv->frame.bitpool; + + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); } - samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); + if (!output) + return framelen; - if (!sbc->data) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = malloc(sbc->size); - } + if (written) + *written = 0; - if (sbc->size < samples * priv->frame.channels * 2) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = realloc(sbc->data, sbc->size); - } + samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + ptr = output; - ptr = sbc->data; + if (output_len < samples * priv->frame.channels * 2) + samples = output_len / (priv->frame.channels * 2); for (i = 0; i < samples; i++) { for (ch = 0; ch < priv->frame.channels; ch++) { @@ -1293,22 +1293,27 @@ } } - sbc->len = samples * priv->frame.channels * 2; + if (written) + *written = samples * priv->frame.channels * 2; return framelen; } -int sbc_encode(sbc_t *sbc, void *data, int count) +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; + if (written) + *written = 0; + if (!priv->init) { priv->frame.sampling_frequency = sbc->rate; priv->frame.channels = sbc->channels; @@ -1325,16 +1330,22 @@ priv->frame.subbands = sbc->subbands; priv->frame.blocks = sbc->blocks; priv->frame.bitpool = sbc->bitpool; + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); sbc_encoder_init(&priv->enc_state, &priv->frame); priv->init = 1; } /* input must be large enough to encode a complete frame */ - if (count < priv->frame.subbands * priv->frame.blocks * sbc->channels * 2) + if (input_len < priv->frame.codesize) return 0; - ptr = data; + /* output must be large enough to receive the encoded frame */ + if (!output || output_len < priv->frame.length) + return -ENOSPC; + + ptr = input; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { for (ch = 0; ch < sbc->channels; ch++) { @@ -1351,19 +1362,10 @@ samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); - if (!sbc->data) { - sbc->size = 1024; - sbc->data = malloc(sbc->size); - } - - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + framelen = sbc_pack_frame(output, &priv->frame, 1024); - framelen = sbc_pack_frame(sbc->data, &priv->frame, sbc->size); - - sbc->len = framelen; + if (written) + *written = framelen; sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate; @@ -1375,11 +1377,29 @@ if (!sbc) return; - if (sbc->data) - free(sbc->data); - if (sbc->priv) free(sbc->priv); memset(sbc, 0, sizeof(sbc_t)); } + +int sbc_get_frame_length(sbc_t *sbc) +{ + int ret; + + ret = 4 + (4 * sbc->subbands * sbc->channels) / 8; + + /* This term is not always evenly device so we round it up */ + if (sbc->channels == 1) + ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; + else + ret += ((sbc->joint * sbc->subbands + sbc->blocks * sbc->bitpool) + + 7) / 8; + + return ret; +} + +int sbc_get_codesize(sbc_t *sbc) +{ + return sbc->subbands * sbc->blocks * sbc->channels * 2; +} Index: sbc/sbc.h =================================================================== RCS file: /cvsroot/bluez/utils/sbc/sbc.h,v retrieving revision 1.6 diff -u -r1.6 sbc.h --- sbc/sbc.h 26 Aug 2007 13:54:24 -0000 1.6 +++ sbc/sbc.h 12 Nov 2007 17:47:28 -0000 @@ -42,10 +42,6 @@ int bitpool; int swap; - void *data; - int size; - int len; - unsigned long duration; void *priv; @@ -54,9 +50,13 @@ typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); -int sbc_parse(sbc_t *sbc, void *data, int count); -int sbc_decode(sbc_t *sbc, void *data, int count); -int sbc_encode(sbc_t *sbc, void *data, int count); +int sbc_parse(sbc_t *sbc, void *input, int input_len); +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *len); +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written); +int sbc_get_frame_length(sbc_t *sbc); +int sbc_get_codesize(sbc_t *sbc); void sbc_finish(sbc_t *sbc); #ifdef __cplusplus Index: sbc/sbcdec.c =================================================================== RCS file: /cvsroot/bluez/utils/sbc/sbcdec.c,v retrieving revision 1.8 diff -u -r1.8 sbcdec.c --- sbc/sbcdec.c 1 Nov 2007 15:27:38 -0000 1.8 +++ sbc/sbcdec.c 12 Nov 2007 17:47:28 -0000 @@ -46,7 +46,7 @@ struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, written; + int fd, ad, pos, streamlen, framelen, count, written, len; int format = AFMT_S16_BE; if (stat(filename, &st) < 0) { @@ -97,7 +97,7 @@ sbc_init(&sbc, 0L); sbc.swap = 1; - framelen = sbc_decode(&sbc, stream, streamlen); + framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len); printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { @@ -125,7 +125,7 @@ * length of the frame we just decoded count is the number of * decoded bytes yet to be written */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { /* buffer is too full to stuff decoded audio in so it * must be written to the device */ written = write(ad, buf, count); @@ -134,23 +134,23 @@ } /* sanity check */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded" - " data (%d)\n", BUF_SIZE, sbc.len + count); + " data (%d)\n", BUF_SIZE, len + count); exit(1); } - /* move the latest decoded data into buf and increase - * the count */ - memcpy(buf + count, sbc.data, sbc.len); - count += sbc.len; + /* increase the count */ + count += len; /* push the pointer in the file forward to the next bit to be * decoded tell the decoder to decode up to the remaining * length of the file (!) */ pos += framelen; - framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); + framelen = sbc_decode(&sbc, stream + pos, streamlen - pos, + buf + count, sizeof(buf) - count, + &len); } if (count > 0) { Index: sbc/sbcenc.c =================================================================== RCS file: /cvsroot/bluez/utils/sbc/sbcenc.c,v retrieving revision 1.5 diff -u -r1.5 sbcenc.c --- sbc/sbcenc.c 1 Nov 2007 15:27:38 -0000 1.5 +++ sbc/sbcenc.c 12 Nov 2007 17:47:28 -0000 @@ -104,9 +104,9 @@ static void encode(char *filename, int subbands, int joint) { struct au_header *au_hdr; - unsigned char buf[2048]; + unsigned char input[2048], output[2048]; sbc_t sbc; - int fd, len, size, count; + int fd, len, size, count, encoded; if (strcmp(filename, "-")) { fd = open(filename, O_RDONLY); @@ -118,7 +118,7 @@ } else fd = fileno(stdin); - len = __read(fd, buf, sizeof(buf)); + len = __read(fd, input, sizeof(input)); if (len < sizeof(*au_hdr)) { if (fd > fileno(stderr)) fprintf(stderr, "Can't read header from file %s: %s\n", @@ -128,7 +128,7 @@ goto done; } - au_hdr = (struct au_header *) buf; + au_hdr = (struct au_header *) input; if (au_hdr->magic != AU_MAGIC || BE_INT(au_hdr->hdr_size) > 128 || @@ -147,11 +147,11 @@ sbc.swap = 1; count = BE_INT(au_hdr->data_size); size = len - BE_INT(au_hdr->hdr_size); - memmove(buf, buf + BE_INT(au_hdr->hdr_size), size); + memmove(input, input + BE_INT(au_hdr->hdr_size), size); while (1) { - if (size < sizeof(buf)) { - len = __read(fd, buf + size, sizeof(buf) - size); + if (size < sizeof(input)) { + len = __read(fd, input + size, sizeof(input) - size); if (len == 0) break; @@ -163,17 +163,18 @@ size += len; } - len = sbc_encode(&sbc, buf, size); + len = sbc_encode(&sbc, input, size, output, sizeof(output), + &encoded); if (len < size) - memmove(buf, buf + len, size - len); + memmove(input, input + len, size - len); size -= len; - len = __write(fileno(stdout), sbc.data, sbc.len); + len = __write(fileno(stdout), output, encoded); if (len == 0) break; - if (len < 0 || len != sbc.len) { + if (len < 0 || len != encoded) { perror("Can't write SBC output"); break; }