Shut up Wmaybe-uninitialized.
[platform/upstream/libaec.git] / src / aec.c
1 /**
2  * @file aec.c
3  *
4  * @author Mathis Rosenhauer, Deutsches Klimarechenzentrum
5  * @author Moritz Hanke, Deutsches Klimarechenzentrum
6  * @author Joerg Behrens, Deutsches Klimarechenzentrum
7  * @author Luis Kornblueh, Max-Planck-Institut fuer Meteorologie
8  *
9  * @section LICENSE
10  * Copyright 2012 - 2014
11  *
12  * Mathis Rosenhauer,                 Luis Kornblueh
13  * Moritz Hanke,
14  * Joerg Behrens
15  *
16  * Deutsches Klimarechenzentrum GmbH  Max-Planck-Institut fuer Meteorologie
17  * Bundesstr. 45a                     Bundesstr. 53
18  * 20146 Hamburg                      20146 Hamburg
19  * Germany                            Germany
20  *
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above
30  *    copyright notice, this list of conditions and the following
31  *    disclaimer in the documentation and/or other materials provided
32  *    with the distribution.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
37  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
38  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
43  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
45  * OF THE POSSIBILITY OF SUCH DAMAGE.
46  *
47  * @section DESCRIPTION
48  *
49  * CLI frontend for Adaptive Entropy Coding library
50  *
51  */
52
53 #include <ctype.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <string.h>
58
59 #ifndef _AIX
60 #include <getopt.h>
61 #endif
62
63 #include <libaec.h>
64
65 #define CHUNK 10485760
66
67 int main(int argc, char *argv[])
68 {
69     struct aec_stream strm;
70     unsigned char *in;
71     unsigned char *out;
72     size_t total_out;
73     int chunk, status, c;
74     int input_avail, output_avail;
75     char *outfn, *infn, *ext;
76     FILE *infp, *outfp;
77     int cflag = 0;
78     int dflag = 0;
79
80     chunk = CHUNK;
81     strm.bits_per_sample = 8;
82     strm.block_size = 8;
83     strm.rsi = 2;
84     strm.flags = AEC_DATA_PREPROCESS;
85     opterr = 0;
86     outfn = 0;
87
88     while ((c = getopt (argc, argv, "3Nb:cdj:mn:pr:st")) != -1)
89         switch (c) {
90         case '3':
91             strm.flags |= AEC_DATA_3BYTE;
92             break;
93         case 'N':
94             strm.flags &= ~AEC_DATA_PREPROCESS;
95             break;
96         case 'b':
97             chunk = atoi(optarg);
98             break;
99         case 'c':
100             cflag = 1;
101             break;
102         case 'd':
103             dflag = 1;
104             break;
105         case 'j':
106             strm.block_size = atoi(optarg);
107             break;
108         case 'm':
109             strm.flags |= AEC_DATA_MSB;
110             break;
111         case 'n':
112             strm.bits_per_sample = atoi(optarg);
113             break;
114         case 'p':
115             strm.flags |= AEC_PAD_RSI;
116             break;
117         case 'r':
118             strm.rsi = atoi(optarg);
119             break;
120         case 's':
121             strm.flags |= AEC_DATA_SIGNED;
122             break;
123         case 't':
124             strm.flags |= AEC_RESTRICTED;
125             break;
126         case '?':
127             if (optopt == 'b')
128                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
129             else if (isprint (optopt))
130                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
131             else
132                 fprintf (stderr,
133                          "Unknown option character `\\x%x'.\n",
134                          optopt);
135             return 1;
136         default:
137             abort ();
138         }
139
140     if (optind < argc) {
141         infn = argv[optind];
142     } else {
143         fprintf(stderr, "Usage: %s [OPTION] SOURCE\n", argv[0]);
144         fprintf(stderr, "\nOPTIONS\n");
145         fprintf(stderr, "-3\n   24 bit samples are stored in 3 bytes\n");
146         fprintf(stderr, "-N\n   disable pre/post processing\n");
147         fprintf(stderr, "-b size\n   internal buffer size in bytes\n");
148         fprintf(stderr, "-c\n   write output on standard output\n");
149         fprintf(stderr, "-d\n   decode SOURCE. If -d is not used: encode.\n");
150         fprintf(stderr, "-j samples\n   block size in samples\n");
151         fprintf(stderr, "-m\n   samples are MSB first. Default is LSB\n");
152         fprintf(stderr, "-n bits\n   bits per sample\n");
153         fprintf(stderr, "-p\n   pad RSI to byte boundary\n");
154         fprintf(stderr, "-r blocks\n   reference sample interval in blocks\n");
155         fprintf(stderr, "-s\n   samples are signed. Default is unsigned\n");
156         fprintf(stderr, "-t\n   use restricted set of code options\n\n");
157         exit(-1);
158     }
159
160     if (strm.bits_per_sample > 16) {
161         if (strm.bits_per_sample <= 24 && strm.flags & AEC_DATA_3BYTE)
162             chunk *= 3;
163         else
164             chunk *= 4;
165     } else if (strm.bits_per_sample > 8) {
166         chunk *= 2;
167     }
168
169     out = (unsigned char *)malloc(chunk);
170     in = (unsigned char *)malloc(chunk);
171
172
173     if (in == NULL || out == NULL)
174         exit(-1);
175
176     total_out = 0;
177     strm.avail_in = 0;
178     strm.avail_out = chunk;
179     strm.next_out = out;
180
181     input_avail = 1;
182     output_avail = 1;
183
184     if ((infp = fopen(infn, "r")) == NULL)
185         exit(-1);
186
187     if (cflag) {
188         outfp = stdout;
189     } else {
190         outfn = malloc(strlen(infn) + 4);
191         if (outfn == NULL)
192             exit(-1);
193
194         if (dflag) {
195             if ((ext = strstr(infn, ".rz")) == NULL) {
196                 fprintf(stderr, "ERROR: input file needs to end with .rz\n");
197                 exit(-1);
198             }
199             strncpy(outfn, infn, ext - infn);
200         } else {
201             sprintf(outfn, "%s.rz", infn);
202         }
203
204         if ((outfp = fopen(outfn, "w")) == NULL)
205             exit(-1);
206     }
207
208     if (dflag) {
209         if (aec_decode_init(&strm) != AEC_OK) {
210             fprintf(stderr, "ERROR: Initialization failed\n");
211             return 1;
212         }
213     } else {
214         if (aec_encode_init(&strm) != AEC_OK) {
215             fprintf(stderr, "ERROR: Initialization failed\n");
216             return 1;
217         }
218     }
219
220     while(input_avail || output_avail) {
221         if (strm.avail_in == 0 && input_avail) {
222             strm.avail_in = fread(in, 1, chunk, infp);
223             if (strm.avail_in != chunk)
224                 input_avail = 0;
225             strm.next_in = in;
226         }
227
228         if (dflag)
229             status = aec_decode(&strm, AEC_NO_FLUSH);
230         else
231             status = aec_encode(&strm, AEC_NO_FLUSH);
232
233         if (status != AEC_OK) {
234             fprintf(stderr, "ERROR: %i\n", status);
235             return 1;
236         }
237
238         if (strm.total_out - total_out > 0) {
239             fwrite(out, strm.total_out - total_out, 1, outfp);
240             total_out = strm.total_out;
241             output_avail = 1;
242             strm.next_out = out;
243             strm.avail_out = chunk;
244         } else {
245             output_avail = 0;
246         }
247
248     }
249
250     if (dflag) {
251         aec_decode_end(&strm);
252     } else {
253         if ((status = aec_encode(&strm, AEC_FLUSH)) != AEC_OK) {
254             fprintf(stderr, "ERROR: %i\n", status);
255             return 1;
256         }
257
258         if (strm.total_out - total_out > 0)
259             fwrite(out, strm.total_out - total_out, 1, outfp);
260
261         aec_encode_end(&strm);
262     }
263
264     fclose(infp);
265     fclose(outfp);
266     free(in);
267     free(out);
268     if (!cflag) {
269         unlink(infn);
270         free(outfn);
271     }
272     return 0;
273 }