From e010fc175e9bedbd5d099f7e32068ad8a051cbec Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Fri, 16 Jan 2009 17:23:54 +0200 Subject: Performance optimizations for sbcenc utility Read and write buffers sizes increased, memmove overhead eliminated. Nonportable cast from 'unsigned char *' to 'struct au_header *' is now also resolved as part of the changes. --- sbc/sbcenc.c | 122 ++++++++++++++++++++++++----------------------------------- 1 file changed, 50 insertions(+), 72 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 9cbfb871..388be2a4 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -40,45 +40,15 @@ static int verbose = 0; -static ssize_t __read(int fd, void *buf, size_t count) -{ - ssize_t len, pos = 0; - - while (count > 0) { - len = read(fd, buf + pos, count); - if (len <= 0) - return pos > len ? pos : len; - - count -= len; - pos += len; - } - - return pos; -} - -static ssize_t __write(int fd, const void *buf, size_t count) -{ - ssize_t len, pos = 0; - - while (count > 0) { - len = write(fd, buf + pos, count); - if (len <= 0) - return len; - - count -= len; - pos += len; - } - - return pos; -} +#define BUF_SIZE 32768 +static unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4]; static void encode(char *filename, int subbands, int bitpool, int joint, int dualchannel, int snr, int blocks) { - struct au_header *au_hdr; - unsigned char input[2048], output[2048]; + struct au_header au_hdr; sbc_t sbc; - int fd, len, size, count, encoded, srate; + int fd, len, size, count, encoded, srate, codesize, nframes; if (strcmp(filename, "-")) { fd = open(filename, O_RDONLY); @@ -90,8 +60,8 @@ static void encode(char *filename, int subbands, int bitpool, int joint, } else fd = fileno(stdin); - len = __read(fd, input, sizeof(input)); - if (len < sizeof(*au_hdr)) { + len = read(fd, &au_hdr, sizeof(au_hdr)); + if (len < sizeof(au_hdr)) { if (fd > fileno(stderr)) fprintf(stderr, "Can't read header from file %s: %s\n", filename, strerror(errno)); @@ -100,19 +70,17 @@ static void encode(char *filename, int subbands, int bitpool, int joint, goto done; } - au_hdr = (struct au_header *) input; - - if (au_hdr->magic != AU_MAGIC || - BE_INT(au_hdr->hdr_size) > 128 || - BE_INT(au_hdr->hdr_size) < 24 || - BE_INT(au_hdr->encoding) != AU_FMT_LIN16) { + if (au_hdr.magic != AU_MAGIC || + BE_INT(au_hdr.hdr_size) > 128 || + BE_INT(au_hdr.hdr_size) < 24 || + BE_INT(au_hdr.encoding) != AU_FMT_LIN16) { fprintf(stderr, "Not in Sun/NeXT audio S16_BE format\n"); goto done; } sbc_init(&sbc, 0L); - switch (BE_INT(au_hdr->sample_rate)) { + switch (BE_INT(au_hdr.sample_rate)) { case 16000: sbc.frequency = SBC_FREQ_16000; break; @@ -127,11 +95,11 @@ static void encode(char *filename, int subbands, int bitpool, int joint, break; } - srate = BE_INT(au_hdr->sample_rate); + srate = BE_INT(au_hdr.sample_rate); sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8; - if (BE_INT(au_hdr->channels) == 1) { + if (BE_INT(au_hdr.channels) == 1) { sbc.mode = SBC_MODE_MONO; if (joint || dualchannel) { fprintf(stderr, "Audio is mono but joint or " @@ -151,9 +119,9 @@ static void encode(char *filename, int subbands, int bitpool, int joint, } sbc.endian = SBC_BE; - count = BE_INT(au_hdr->data_size); - size = len - BE_INT(au_hdr->hdr_size); - memmove(input, input + BE_INT(au_hdr->hdr_size), size); + count = BE_INT(au_hdr.data_size); + size = len - BE_INT(au_hdr.hdr_size); + memmove(input, input + BE_INT(au_hdr.hdr_size), size); sbc.bitpool = bitpool; sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS; @@ -172,37 +140,47 @@ static void encode(char *filename, int subbands, int bitpool, int joint, "STEREO" : "JOINTSTEREO"); } + codesize = sbc_get_codesize(&sbc); + nframes = sizeof(input) / codesize; while (1) { - if (size < sizeof(input)) { - len = __read(fd, input + size, sizeof(input) - size); - if (len == 0 && size == 0) - break; - - if (len < 0) { - perror("Can't read audio data"); + unsigned char *inp, *outp; + /* read data for up to 'nframes' frames of input data */ + size = read(fd, input, codesize * nframes); + if (size < 0) { + /* Something really bad happened */ + perror("Can't read audio data"); + break; + } + if (size < codesize) { + /* Not enough data for encoding even a single frame */ + break; + } + /* encode all the data from the input buffer in a loop */ + inp = input; + outp = output; + while (size >= codesize) { + len = sbc_encode(&sbc, inp, codesize, + outp, sizeof(output) - (outp - output), + &encoded); + if (len != codesize || encoded <= 0) { + fprintf(stderr, + "sbc_encode fail, len=%d, encoded=%d\n", + len, encoded); break; } - - size += len; + size -= len; + inp += len; + outp += encoded; } - - len = sbc_encode(&sbc, input, size, - output, sizeof(output), &encoded); - if (len <= 0) - break; - if (len < size) - memmove(input, input + len, size - len); - - size -= len; - - len = __write(fileno(stdout), output, encoded); - if (len == 0) - break; - - if (len < 0 || len != encoded) { + len = write(fileno(stdout), output, outp - output); + if (len != outp - output) { perror("Can't write SBC output"); break; } + if (size >= codesize) { + /* sbc_encode failure has been detected earlier */ + break; + } } sbc_finish(&sbc); -- cgit