OSDN Git Service

Performance optimizations for sbcenc utility
authorSiarhei Siamashka <siarhei.siamashka@nokia.com>
Fri, 16 Jan 2009 15:23:54 +0000 (17:23 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sun, 18 Jan 2009 15:14:46 +0000 (16:14 +0100)
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

index 9cbfb87..388be2a 100644 (file)
 
 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);