Small PP improvement, avoid buffer copy
[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
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 1024
66
67 int main(int argc, char *argv[])
68 {
69     struct aec_stream strm;
70     unsigned char *in;
71     unsigned char *out;
72     int chunk, total_out, status, c;
73     int input_avail, output_avail;
74     char *outfn, *infn, *ext;
75     FILE *infp, *outfp;
76     int cflag = 0;
77     int dflag = 0;
78
79     chunk = CHUNK;
80     strm.bits_per_sample = 8;
81     strm.block_size = 8;
82     strm.rsi = 2;
83     strm.flags = AEC_DATA_PREPROCESS;
84     opterr = 0;
85
86     while ((c = getopt (argc, argv, "d3Mscb:B:R:J:")) != -1)
87         switch (c)
88         {
89         case 'd':
90             dflag = 1;
91             break;
92         case 'b':
93             chunk = atoi(optarg);
94             break;
95         case 'B':
96             strm.bits_per_sample = atoi(optarg);
97             break;
98         case 'J':
99             strm.block_size = atoi(optarg);
100             break;
101         case 'R':
102             strm.rsi = atoi(optarg);
103             break;
104         case 'c':
105             cflag = 1;
106             break;
107         case 's':
108             strm.flags |= AEC_DATA_SIGNED;
109             break;
110         case 'M':
111             strm.flags |= AEC_DATA_MSB;
112             break;
113         case '3':
114             strm.flags |= AEC_DATA_3BYTE;
115             break;
116         case '?':
117             if (optopt == 'b')
118                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
119             else if (isprint (optopt))
120                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
121             else
122                 fprintf (stderr,
123                          "Unknown option character `\\x%x'.\n",
124                          optopt);
125             return 1;
126         default:
127             abort ();
128         }
129
130     if (optind < argc)
131     {
132         infn = argv[optind];
133     }
134     else
135     {
136         fprintf(stderr, "Usage: %s [ -c ] [ -b chunksize ] name\n", argv[0]);
137         exit(-1);
138     }
139
140     if (strm.bits_per_sample > 16)
141     {
142         if (strm.bits_per_sample <= 24 && strm.flags & AEC_DATA_3BYTE)
143             chunk *= 3;
144         else
145             chunk *= 4;
146     }
147     else if (strm.bits_per_sample > 8)
148     {
149         chunk *= 2;
150     }
151
152     out = (unsigned char *)malloc(chunk);
153     in = (unsigned char *)malloc(chunk);
154
155
156     if (in == NULL || out == NULL)
157         exit(-1);
158
159     total_out = 0;
160     strm.avail_in = 0;
161     strm.avail_out = chunk;
162     strm.next_out = out;
163
164     input_avail = 1;
165     output_avail = 1;
166
167     if ((infp = fopen(infn, "r")) == NULL)
168         exit(-1);
169
170     if (cflag)
171     {
172         outfp = stdout;
173     }
174     else
175     {
176         outfn = malloc(strlen(infn) + 4);
177         if (outfn == NULL)
178             exit(-1);
179
180         if (dflag)
181         {
182             if ((ext = strstr(infn, ".aec")) == NULL)
183             {
184                 fprintf(stderr, "Error: input file needs to end with .aec\n");
185                 exit(-1);
186             }
187             strncpy(outfn, infn, ext - infn);
188         }
189         else
190         {
191             sprintf(outfn, "%s.aec", infn);
192         }
193
194         if ((outfp = fopen(outfn, "w")) == NULL)
195             exit(-1);
196     }
197
198     if (dflag)
199     {
200         if (aec_decode_init(&strm) != AEC_OK)
201             return 1;
202     }
203     else
204     {
205         if (aec_encode_init(&strm) != AEC_OK)
206             return 1;
207     }
208
209     while(input_avail || output_avail)
210     {
211         if (strm.avail_in == 0 && input_avail)
212         {
213             strm.avail_in = fread(in, 1, chunk, infp);
214             if (strm.avail_in != chunk)
215                 input_avail = 0;
216             strm.next_in = in;
217         }
218
219         if (dflag)
220             status = aec_decode(&strm, AEC_NO_FLUSH);
221         else
222             status = aec_encode(&strm, AEC_NO_FLUSH);
223
224         if (status != AEC_OK)
225         {
226             fprintf(stderr, "error is %i\n", status);
227             return 1;
228         }
229
230         if (strm.total_out - total_out > 0)
231         {
232             fwrite(out, strm.total_out - total_out, 1, outfp);
233             total_out = strm.total_out;
234             output_avail = 1;
235             strm.next_out = out;
236             strm.avail_out = chunk;
237         }
238         else
239         {
240             output_avail = 0;
241         }
242
243     }
244
245     if (dflag)
246     {
247         aec_decode_end(&strm);
248     }
249     else
250     {
251         if ((status = aec_encode(&strm, AEC_FLUSH)) != AEC_OK)
252         {
253             fprintf(stderr, "error is %i\n", status);
254             return 1;
255         }
256
257         if (strm.total_out - total_out > 0)
258         {
259             fwrite(out, strm.total_out - total_out, 1, outfp);
260         }
261
262         aec_encode_end(&strm);
263     }
264
265     fclose(infp);
266     fclose(outfp);
267     free(in);
268     free(out);
269     if (!cflag)
270     {
271         unlink(infn);
272         free(outfn);
273     }
274     return 0;
275 }