aec.c 4.66 KB
Newer Older
1 2 3 4 5 6
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <string.h>
7
#include <getopt.h>
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
8
#include "libaec.h"
9 10 11 12 13

#define CHUNK 1024

int main(int argc, char *argv[])
{
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
14
    struct aec_stream strm;
15 16 17 18
    uint8_t *in;
    uint8_t *out;
    int chunk, total_out, status, c;
    int input_avail, output_avail;
19
    char *outfn, *infn, *ext;
20 21
    FILE *infp, *outfp;
    int cflag = 0;
22
    int dflag = 0;
23 24

    chunk = CHUNK;
25 26
    strm.bit_per_sample = 8;
    strm.block_size = 8;
27
    strm.rsi = 2;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
28
    strm.flags = AEC_DATA_PREPROCESS;
29 30
    opterr = 0;

31
    while ((c = getopt (argc, argv, "d3Mscb:B:R:J:")) != -1)
32 33
        switch (c)
        {
34 35 36
        case 'd':
            dflag = 1;
            break;
37
        case 'b':
38
            chunk = atoi(optarg);
39
            break;
40 41 42
        case 'B':
            strm.bit_per_sample = atoi(optarg);
            break;
43 44 45
        case 'J':
            strm.block_size = atoi(optarg);
            break;
46 47
        case 'R':
            strm.rsi = atoi(optarg);
48
            break;
49 50 51
        case 'c':
            cflag = 1;
            break;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
52
        case 's':
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
53
            strm.flags |= AEC_DATA_SIGNED;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
54
            break;
55
        case 'M':
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
56
            strm.flags |= AEC_DATA_MSB;
57
            break;
58
        case '3':
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
59
            strm.flags |= AEC_DATA_3BYTE;
60
            break;
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
        case '?':
            if (optopt == 'b')
                fprintf (stderr, "Option -%c requires an argument.\n", optopt);
            else if (isprint (optopt))
                fprintf (stderr, "Unknown option `-%c'.\n", optopt);
            else
                fprintf (stderr,
                         "Unknown option character `\\x%x'.\n",
                         optopt);
            return 1;
        default:
            abort ();
        }

    if (optind < argc)
    {
        infn = argv[optind];
    }
    else
    {
        fprintf(stderr, "Usage: %s [ -c ] [ -b chunksize ] name\n", argv[0]);
        exit(-1);
    }

85 86
    if (strm.bit_per_sample > 16)
    {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
87
        if (strm.bit_per_sample <= 24 && strm.flags & AEC_DATA_3BYTE)
88 89 90 91 92 93 94 95 96
            chunk *= 3;
        else
            chunk *= 4;
    }
    else if (strm.bit_per_sample > 8)
    {
        chunk *= 2;
    }

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    out = (uint8_t *)malloc(chunk);
    in = (uint8_t *)malloc(chunk);


    if (in == NULL || out == NULL)
        exit(-1);

    total_out = 0;
    strm.avail_in = 0;
    strm.avail_out = chunk;
    strm.next_out = out;

    input_avail = 1;
    output_avail = 1;

    if ((infp = fopen(infn, "r")) == NULL)
        exit(-1);

    if (cflag)
    {
        outfp = stdout;
    }
    else
    {
        outfn = malloc(strlen(infn) + 4);
        if (outfn == NULL)
            exit(-1);

125 126
        if (dflag)
        {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
127
            if ((ext = strstr(infn, ".aec")) == NULL)
128
            {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
129
                fprintf(stderr, "Error: input file needs to end with .aec\n");
130 131 132 133 134 135
                exit(-1);
            }
            strncpy(outfn, infn, ext - infn);
        }
        else
        {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
136
            sprintf(outfn, "%s.aec", infn);
137
        }
138 139 140 141 142

        if ((outfp = fopen(outfn, "w")) == NULL)
            exit(-1);
    }

143 144
    if (dflag)
    {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
145
        if (aec_decode_init(&strm) != AEC_OK)
146 147 148 149
            return 1;
    }
    else
    {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
150
        if (aec_encode_init(&strm) != AEC_OK)
151 152 153
            return 1;
    }

154 155 156 157 158 159 160 161 162 163
    while(input_avail || output_avail)
    {
        if (strm.avail_in == 0 && input_avail)
        {
            strm.avail_in = fread(in, 1, chunk, infp);
            if (strm.avail_in != chunk)
                input_avail = 0;
            strm.next_in = (uint8_t *)in;
        }

164
        if (dflag)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
165
            status = aec_decode(&strm, AEC_NO_FLUSH);
166
        else
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
167
            status = aec_encode(&strm, AEC_NO_FLUSH);
168

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
169
        if (status != AEC_OK)
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
        {
            fprintf(stderr, "error is %i\n", status);
            return 1;
        }

        if (strm.total_out - total_out > 0)
        {
            fwrite(out, strm.total_out - total_out, 1, outfp);
            total_out = strm.total_out;
            output_avail = 1;
            strm.next_out = out;
            strm.avail_out = chunk;
        }
        else
        {
            output_avail = 0;
        }

    }

190
    if (dflag)
191
    {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
192
        aec_decode_end(&strm);
193
    }
194
    else
195
    {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
196
        if ((status = aec_encode(&strm, AEC_FLUSH)) != AEC_OK)
197 198 199 200 201 202 203 204 205 206
        {
            fprintf(stderr, "error is %i\n", status);
            return 1;
        }

        if (strm.total_out - total_out > 0)
        {
            fwrite(out, strm.total_out - total_out, 1, outfp);
        }

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
207
        aec_encode_end(&strm);
208 209 210 211 212 213 214 215 216 217 218 219 220
    }

    fclose(infp);
    fclose(outfp);
    free(in);
    free(out);
    if (!cflag)
    {
        unlink(infn);
        free(outfn);
    }
    return 0;
}