diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-11-12 18:15:59 +0000 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-11-12 18:15:59 +0000 |
commit | 397d6c2b3bc7661f978c1777442d33fd86ada21e (patch) | |
tree | 7ac2b0d3768715896e286eab291dccfde333cfb8 /sbc | |
parent | f89c7796c7882c65e829e5203a79606c3d1d63b0 (diff) |
Make sbc codec to write directly in application buffers and so avoiding memcpys.
Diffstat (limited to 'sbc')
-rw-r--r-- | sbc/sbc.c | 98 | ||||
-rw-r--r-- | sbc/sbc.h | 14 | ||||
-rw-r--r-- | sbc/sbcdec.c | 20 | ||||
-rw-r--r-- | sbc/sbcenc.c | 23 |
4 files changed, 88 insertions, 67 deletions
@@ -95,6 +95,8 @@ struct sbc_frame { } 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 @@ int sbc_init(sbc_t *sbc, unsigned long flags) 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 @@ int sbc_decode(sbc_t *sbc, void *data, int count) 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 @@ int sbc_decode(sbc_t *sbc, void *data, int count) } } - 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 @@ int sbc_encode(sbc_t *sbc, void *data, int count) 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 @@ int sbc_encode(sbc_t *sbc, void *data, int count) 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, output_len); - 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 @@ void sbc_finish(sbc_t *sbc) 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 devide 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; +} @@ -42,10 +42,6 @@ struct sbc_struct { int bitpool; int swap; - void *data; - int size; - int len; - unsigned long duration; void *priv; @@ -54,9 +50,13 @@ struct sbc_struct { 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 diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 866b8448..09a211a1 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,7 @@ static void decode(char *filename, char *output, int tofile) 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 @@ static void decode(char *filename, char *output, int tofile) 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 @@ static void decode(char *filename, char *output, int tofile) * 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 @@ static void decode(char *filename, char *output, int tofile) } /* 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) { diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 94b9f642..cba31c7b 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -104,9 +104,9 @@ static ssize_t __write(int fd, const void *buf, size_t count) 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 @@ static void encode(char *filename, int subbands, int joint) } 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 @@ static void encode(char *filename, int subbands, int joint) 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 @@ static void encode(char *filename, int subbands, int joint) 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 @@ static void encode(char *filename, int subbands, int joint) 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; } |