Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / common tools sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/base_coding.h>
27 : #include <gpac/constants.h>
28 :
29 : #ifndef GPAC_DISABLE_CORE_TOOLS
30 :
31 : static const char base_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 :
33 : GF_EXPORT
34 125 : u32 gf_base64_encode(const u8 *_in, u32 inSize, u8 *_out, u32 outSize)
35 : {
36 : s32 padding;
37 : u32 i = 0, j = 0;
38 : unsigned char *in = (unsigned char *)_in;
39 : unsigned char *out = (unsigned char *)_out;
40 :
41 125 : if (outSize < (inSize * 4 / 3)) return 0;
42 :
43 47201 : while (i < inSize) {
44 47076 : padding = 3 - (inSize - i);
45 47076 : if (padding == 2) {
46 41 : out[j] = base_64[in[i]>>2];
47 41 : out[j+1] = base_64[(in[i] & 0x03) << 4];
48 41 : out[j+2] = '=';
49 41 : out[j+3] = '=';
50 47035 : } else if (padding == 1) {
51 51 : out[j] = base_64[in[i]>>2];
52 51 : out[j+1] = base_64[((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4)];
53 51 : out[j+2] = base_64[(in[i+1] & 0x0f) << 2];
54 51 : out[j+3] = '=';
55 : } else {
56 46984 : out[j] = base_64[in[i]>>2];
57 46984 : out[j+1] = base_64[((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4)];
58 46984 : out[j+2] = base_64[((in[i+1] & 0x0f) << 2) | ((in[i+2] & 0xc0) >> 6)];
59 46984 : out[j+3] = base_64[in[i+2] & 0x3f];
60 : }
61 47076 : i += 3;
62 47076 : j += 4;
63 : }
64 : return j;
65 : }
66 :
67 : static const unsigned char index_64[128] = {
68 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
71 : 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 : 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
73 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
74 : 0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
75 : 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff
76 : };
77 :
78 : #define char64(c) ((c > 127) ? (char) 0xff : index_64[(c)])
79 :
80 : /*denoise input*/
81 372 : u32 load_block(char *in, u32 size, u32 pos, char *out)
82 : {
83 : u32 i, len;
84 : u8 c;
85 : len = i = 0;
86 2328 : while ((len<4) && ((pos+i)<size)) {
87 1584 : c = in[pos+i];
88 3168 : if ( ((c>='A') && (c<='Z'))
89 1584 : || ((c>='a') && (c<='z'))
90 356 : || ((c>='0') && (c<='9'))
91 164 : || (c=='=') || (c=='+') || (c=='/')
92 : ) {
93 1480 : out[len] = c;
94 1480 : len++;
95 : }
96 1584 : i++;
97 : }
98 380 : while (len<4) {
99 8 : out[len] = (char) 0xFF;
100 8 : len++;
101 : }
102 372 : return pos+i;
103 : }
104 :
105 : GF_EXPORT
106 24 : u32 gf_base64_decode(u8 *in_buf, u32 inSize, u8 *out, u32 outSize)
107 : {
108 : u32 i = 0, j = 0, padding;
109 : unsigned char c[4], in[4];
110 :
111 24 : if (outSize < (inSize * 3 / 4)) return 0;
112 :
113 396 : while ((i + 3) < inSize) {
114 : padding = 0;
115 372 : i = load_block(in_buf, inSize, i, (char*)in);
116 372 : c[0] = char64(in[0]);
117 372 : padding += (c[0] == 0xff);
118 372 : c[1] = char64(in[1]);
119 372 : padding += (c[1] == 0xff);
120 372 : c[2] = char64(in[2]);
121 372 : padding += (c[2] == 0xff);
122 372 : c[3] = char64(in[3]);
123 372 : padding += (c[3] == 0xff);
124 372 : if (padding == 2) {
125 12 : out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
126 12 : out[j] = (c[1] & 0x0f) << 4;
127 360 : } else if (padding == 1) {
128 4 : out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
129 4 : out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
130 4 : out[j] = (c[2] & 0x03) << 6;
131 : } else {
132 356 : out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
133 356 : out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
134 356 : out[j++] = ((c[2] & 0x03) << 6) | (c[3] & 0x3f);
135 : }
136 : //i += 4;
137 : }
138 : return j;
139 : }
140 :
141 : static const char base_16[] = "0123456789abcdef";
142 :
143 : GF_EXPORT
144 2 : u32 gf_base16_encode(u8 *_in, u32 inSize, u8 *_out, u32 outSize)
145 : {
146 : u32 i = 0;
147 : unsigned char *in = (unsigned char *)_in;
148 : unsigned char *out = (unsigned char *)_out;
149 :
150 2 : if (outSize < (inSize * 2)+1) return 0;
151 :
152 485 : for (i=0; i<inSize; i++) {
153 485 : out[2*i] = base_16[((in[i] & 0xf0) >> 4)];
154 485 : out[2*i+1] = base_16[(in[i] & 0x0f)];
155 : }
156 2 : out[(inSize * 2)] = 0;
157 :
158 2 : return inSize * 2;
159 : }
160 :
161 : #define char16(nb) (((nb) < 97) ? ((nb)-48) : ((nb)-87))
162 :
163 : GF_EXPORT
164 2 : u32 gf_base16_decode(u8 *in, u32 inSize, u8 *out, u32 outSize)
165 : {
166 : u32 j=0;
167 : u32 c[2] = {0,0};
168 :
169 2 : if (outSize < (inSize / 2)) return 0;
170 2 : if ((inSize % 2) != 0) return 0;
171 :
172 485 : for (j=0; j<inSize/2; j++) {
173 485 : c[0] = char16(in[2*j]);
174 485 : c[1] = char16(in[2*j+1]);
175 485 : out[j] = ((c[0] << 4)&0xf0) | (c[1]&0x0f);
176 : }
177 2 : out[inSize/2] = 0;
178 :
179 2 : return j;
180 : }
181 :
182 :
183 : #ifndef GPAC_DISABLE_ZLIB
184 :
185 : #include <zlib.h>
186 :
187 : #define ZLIB_COMPRESS_SAFE 4
188 :
189 : GF_EXPORT
190 48 : GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data)
191 : {
192 : z_stream stream;
193 : int err;
194 48 : char *dest = (char *)gf_malloc(sizeof(char)*data_len*ZLIB_COMPRESS_SAFE);
195 48 : stream.next_in = (Bytef*)(*data) + data_offset;
196 48 : stream.avail_in = (uInt)data_len - data_offset;
197 48 : stream.next_out = ( Bytef*)dest;
198 48 : stream.avail_out = (uInt)data_len*ZLIB_COMPRESS_SAFE;
199 48 : stream.zalloc = (alloc_func)NULL;
200 48 : stream.zfree = (free_func)NULL;
201 48 : stream.opaque = (voidpf)NULL;
202 :
203 48 : err = deflateInit2(&stream, 9, Z_DEFLATED, 16+MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
204 :
205 48 : if (err != Z_OK) {
206 0 : gf_free(dest);
207 0 : return GF_IO_ERR;
208 : }
209 :
210 48 : err = deflate(&stream, Z_FINISH);
211 48 : if (err != Z_STREAM_END) {
212 0 : deflateEnd(&stream);
213 0 : gf_free(dest);
214 0 : return GF_IO_ERR;
215 : }
216 48 : if (data_len-data_offset < stream.total_out) {
217 2 : if (skip_if_larger) {
218 0 : gf_free(dest);
219 0 : deflateEnd(&stream);
220 0 : *max_size = (u32) stream.total_out;
221 0 : return GF_OK;
222 : }
223 2 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[GZ] compressed data (%d) larger than input (%d)\n", (u32) stream.total_out, (u32) data_len ));
224 : }
225 :
226 48 : if (out_comp_data) {
227 : data = out_comp_data;
228 : }
229 :
230 48 : if (*max_size < stream.total_out) {
231 2 : *max_size = data_len*ZLIB_COMPRESS_SAFE;
232 2 : *data = (char*)gf_realloc(*data, *max_size * sizeof(char));
233 : }
234 :
235 48 : memcpy((*data) , dest, sizeof(char)*stream.total_out);
236 48 : *max_size = (u32) stream.total_out;
237 48 : gf_free(dest);
238 :
239 48 : deflateEnd(&stream);
240 48 : return GF_OK;
241 : }
242 :
243 : GF_EXPORT
244 30 : GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
245 : {
246 30 : return gf_gz_compress_payload_ex(data, data_len, max_size, 0, GF_FALSE, NULL);
247 : }
248 :
249 : GF_EXPORT
250 30 : GF_Err gf_gz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
251 : {
252 : z_stream d_stream;
253 : GF_Err e = GF_OK;
254 : int err;
255 : Bool owns_buffer=GF_TRUE;
256 : u32 size = 4096;
257 :
258 30 : if (! *uncompressed_data) {
259 15 : *uncompressed_data = (char*)gf_malloc(sizeof(char)*4096);
260 15 : if (!*uncompressed_data) return GF_OUT_OF_MEM;
261 : } else {
262 : owns_buffer = GF_FALSE;
263 15 : size = *out_size;
264 : }
265 :
266 30 : d_stream.zalloc = (alloc_func)0;
267 30 : d_stream.zfree = (free_func)0;
268 30 : d_stream.opaque = (voidpf)0;
269 30 : d_stream.next_in = (Bytef*)data;
270 30 : d_stream.avail_in = data_len;
271 30 : d_stream.next_out = (Bytef*) *uncompressed_data;
272 30 : d_stream.avail_out = size;
273 :
274 30 : err = inflateInit2(&d_stream, 16+MAX_WBITS);
275 :
276 30 : if (err == Z_OK) {
277 30 : while (d_stream.total_in < data_len) {
278 30 : err = inflate(&d_stream, Z_NO_FLUSH);
279 30 : if (err < Z_OK) {
280 : e = GF_NON_COMPLIANT_BITSTREAM;
281 : break;
282 : }
283 30 : if (err==Z_STREAM_END) break;
284 :
285 0 : size *= 2;
286 0 : *uncompressed_data = (char*)gf_realloc(*uncompressed_data, sizeof(char)*size);
287 0 : if (!*uncompressed_data) return GF_OUT_OF_MEM;
288 0 : d_stream.avail_out = (u32) (size - d_stream.total_out);
289 0 : d_stream.next_out = (Bytef*) ( *uncompressed_data + d_stream.total_out);
290 : }
291 30 : *out_size = (u32) d_stream.total_out;
292 30 : inflateEnd(&d_stream);
293 30 : return e;
294 : }
295 : if (e!=GF_OK) {
296 : if (owns_buffer) {
297 : gf_free(*uncompressed_data);
298 : *uncompressed_data = NULL;
299 : }
300 : }
301 : return e;
302 : }
303 : #else
304 : GF_EXPORT
305 : GF_Err gf_gz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
306 : {
307 : *out_size = 0;
308 : return GF_NOT_SUPPORTED;
309 : }
310 : GF_EXPORT
311 : GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
312 : {
313 : *max_size = 0;
314 : return GF_NOT_SUPPORTED;
315 : }
316 : GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data)
317 : {
318 : *max_size = 0;
319 : return GF_NOT_SUPPORTED;
320 : }
321 : #endif /*GPAC_DISABLE_ZLIB*/
322 :
323 :
324 : #ifdef GPAC_HAS_LZMA
325 :
326 : #include <lzma.h>
327 :
328 : #define LZMA_COMPRESS_SAFE 2
329 :
330 : GF_EXPORT
331 1 : GF_Err gf_lz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
332 : {
333 : u32 block_size, comp_size;
334 : lzma_options_lzma opt_lzma2;
335 1 : lzma_stream strm = LZMA_STREAM_INIT;
336 :
337 1 : lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT);
338 1 : lzma_filter filters[] = {
339 : { .id = LZMA_FILTER_X86, .options = NULL },
340 : { .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
341 : { .id = LZMA_VLI_UNKNOWN, .options = NULL },
342 : };
343 1 : lzma_ret ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_NONE);
344 1 : if (ret != LZMA_OK) return GF_IO_ERR;
345 :
346 1 : block_size = data_len*LZMA_COMPRESS_SAFE;
347 1 : if (block_size < 64) block_size = 64;
348 1 : char *dest = (char *)gf_malloc(sizeof(char)*block_size);
349 :
350 :
351 1 : strm.next_in = (const uint8_t *) (*data);
352 1 : strm.avail_in = data_len;
353 1 : strm.next_out = (uint8_t *) dest;
354 1 : strm.avail_out = block_size;
355 :
356 1 : ret = lzma_code(&strm, LZMA_FINISH);
357 1 : if ((ret != LZMA_OK) && (ret != LZMA_STREAM_END)) {
358 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[LZMA] compressed data failure, code %d\n", ret ));
359 : return GF_IO_ERR;
360 : }
361 1 : comp_size = block_size - strm.avail_out;
362 :
363 1 : if (data_len < comp_size) {
364 1 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[LZMA] compressed data (%d) larger than input (%d)\n", (u32) comp_size, (u32) data_len ));
365 : }
366 :
367 1 : if (*max_size < comp_size) {
368 1 : *max_size = block_size;
369 1 : *data = (char*)gf_realloc(*data, block_size * sizeof(char));
370 : }
371 :
372 1 : memcpy((*data) , dest, sizeof(char) * comp_size);
373 1 : *max_size = (u32) comp_size;
374 1 : gf_free(dest);
375 :
376 1 : lzma_end(&strm);
377 1 : return GF_OK;
378 : }
379 :
380 : GF_EXPORT
381 1 : GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
382 : {
383 1 : lzma_stream strm = LZMA_STREAM_INIT;
384 1 : lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
385 1 : if (ret != LZMA_OK) return GF_IO_ERR;
386 :
387 : Bool owns_buffer=GF_TRUE;
388 : u32 block_size = 4096;
389 : u32 done = 0;
390 : u32 alloc_size = 0;
391 : u8 block[4096];
392 : u8 *dst_buffer = NULL;
393 :
394 1 : if (*uncompressed_data) {
395 : owns_buffer = GF_FALSE;
396 : dst_buffer = (u8 *) *uncompressed_data;
397 0 : alloc_size = *out_size;
398 : } else {
399 1 : *out_size = 0;
400 : }
401 :
402 1 : strm.next_in = (const uint8_t *) data;
403 1 : strm.avail_in = data_len;
404 1 : strm.next_out = (uint8_t *) block;
405 1 : strm.avail_out = block_size;
406 :
407 : while (1) {
408 1 : ret = lzma_code(&strm, LZMA_FINISH);
409 :
410 1 : if ((strm.avail_out == 0) || (ret == LZMA_STREAM_END)) {
411 1 : u32 uncomp_size = block_size - strm.avail_out;
412 :
413 1 : if (done + uncomp_size > alloc_size) {
414 : alloc_size = done + uncomp_size;
415 1 : dst_buffer = gf_realloc(dst_buffer, alloc_size);
416 1 : *out_size = alloc_size;
417 : }
418 1 : memcpy(dst_buffer + done, block, uncomp_size);
419 : done += uncomp_size;
420 :
421 1 : strm.next_out = (uint8_t *) block;
422 1 : strm.avail_out = block_size;
423 : }
424 1 : if (ret == LZMA_STREAM_END) break;
425 0 : if (ret != LZMA_OK) {
426 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[LZMA] error decompressing data: %d\n", ret ));
427 0 : if (owns_buffer) gf_free(dst_buffer);
428 : return GF_IO_ERR;
429 : }
430 : }
431 :
432 1 : *uncompressed_data = dst_buffer;
433 1 : *out_size = done;
434 1 : return GF_OK;
435 : }
436 : #else
437 : GF_EXPORT
438 : GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
439 : {
440 : *out_size = 0;
441 : return GF_NOT_SUPPORTED;
442 : }
443 : GF_EXPORT
444 : GF_Err gf_lz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
445 : {
446 : *max_size = 0;
447 : return GF_NOT_SUPPORTED;
448 : }
449 : #endif /*GPAC_HAS_LZMA*/
450 :
451 : #endif /* GPAC_DISABLE_CORE_TOOLS*/
|