summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/libalac/README43
-rw-r--r--apps/codecs/libalac/alac.c972
-rw-r--r--apps/codecs/libalac/decomp.h13
-rw-r--r--apps/codecs/libalac/demux.c637
-rw-r--r--apps/codecs/libalac/demux.h55
-rw-r--r--apps/codecs/libalac/stream.h30
6 files changed, 1750 insertions, 0 deletions
diff --git a/apps/codecs/libalac/README b/apps/codecs/libalac/README
new file mode 100644
index 0000000000..1b304d2d93
--- /dev/null
+++ b/apps/codecs/libalac/README
@@ -0,0 +1,43 @@
1INSTALLATION:
2-------------
3
4Simply compile by running 'make'
5
6USAGE:
7------
8
9Then run the program, it will give you usage instructions.
10
11It's really quite trivial to use.
12
13For example, to decode input.m4a to output.wav:
14./alac -f output.wav input.m4a
15
16Or, as another example, say if you wanted to stream play
17http://www.mplayerhq.hu/MPlayer/samples/A-codecs/lossless/luckynight.m4a
18and you're system uses the ALSA sound system:
19wget -O - http://www.mplayerhq.hu/MPlayer/samples/A-codecs/lossless/luckynight.m4a | ./alac - | aplay
20
21By default the output file is in WAV format. To output as raw PCM, provide the
22-r option on the command line.
23
24MORE INFORMATION:
25-----------------
26
27Please visit http://crazney.net/programs/itunes/alac.html for more information.
28
29HELP NEEDED:
30------------
31I need help to allow myself to continue hacking on various Apple Audio things, please visit
32http://crazney.net/programs/itunes/help.html
33
34AUTHOR:
35-------
36
37David Hammerton
38
39CONTRIBUTORS:
40-------------
41
42Cody Brocious
43
diff --git a/apps/codecs/libalac/alac.c b/apps/codecs/libalac/alac.c
new file mode 100644
index 0000000000..575bbf5abc
--- /dev/null
+++ b/apps/codecs/libalac/alac.c
@@ -0,0 +1,972 @@
1/*
2 * ALAC (Apple Lossless Audio Codec) decoder
3 * Copyright (c) 2005 David Hammerton
4 * All rights reserved.
5 *
6 * This is the actual decoder.
7 *
8 * http://crazney.net/programs/itunes/alac.html
9 *
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated documentation
12 * files (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use,
14 * copy, modify, merge, publish, distribute, sublicense, and/or
15 * sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 *
30 */
31
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <stdint.h>
37
38#include "decomp.h"
39
40#define _Swap32(v) do { \
41 v = (((v) & 0x000000FF) << 0x18) | \
42 (((v) & 0x0000FF00) << 0x08) | \
43 (((v) & 0x00FF0000) >> 0x08) | \
44 (((v) & 0xFF000000) >> 0x18); } while(0)
45
46#define _Swap16(v) do { \
47 v = (((v) & 0x00FF) << 0x08) | \
48 (((v) & 0xFF00) >> 0x08); } while (0)
49
50
51extern int host_bigendian;
52
53struct alac_file
54{
55 unsigned char *input_buffer;
56 int input_buffer_bitaccumulator; /* used so we can do arbitary
57 bit reads */
58
59 int samplesize;
60 int numchannels;
61 int bytespersample;
62
63
64 /* buffers */
65 int32_t *predicterror_buffer_a;
66 int32_t *predicterror_buffer_b;
67
68 int32_t *outputsamples_buffer_a;
69 int32_t *outputsamples_buffer_b;
70
71
72 /* stuff from setinfo */
73 uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
74 uint8_t setinfo_7a; /* 0x00 */
75 uint8_t setinfo_sample_size; /* 0x10 */
76 uint8_t setinfo_rice_historymult; /* 0x28 */
77 uint8_t setinfo_rice_initialhistory; /* 0x0a */
78 uint8_t setinfo_rice_kmodifier; /* 0x0e */
79 uint8_t setinfo_7f; /* 0x02 */
80 uint16_t setinfo_80; /* 0x00ff */
81 uint32_t setinfo_82; /* 0x000020e7 */
82 uint32_t setinfo_86; /* 0x00069fe4 */
83 uint32_t setinfo_8a_rate; /* 0x0000ac44 */
84 /* end setinfo stuff */
85
86};
87
88
89static void allocate_buffers(alac_file *alac)
90{
91 alac->predicterror_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
92 alac->predicterror_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
93
94 alac->outputsamples_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
95 alac->outputsamples_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
96}
97
98void alac_set_info(alac_file *alac, char *inputbuffer)
99{
100 char *ptr = inputbuffer;
101 ptr += 4; /* size */
102 ptr += 4; /* frma */
103 ptr += 4; /* alac */
104 ptr += 4; /* size */
105 ptr += 4; /* alac */
106
107 ptr += 4; /* 0 ? */
108
109 alac->setinfo_max_samples_per_frame = *(uint32_t*)ptr; /* buffer size / 2 ? */
110 if (!host_bigendian)
111 _Swap32(alac->setinfo_max_samples_per_frame);
112 ptr += 4;
113 alac->setinfo_7a = *(uint8_t*)ptr;
114 ptr += 1;
115 alac->setinfo_sample_size = *(uint8_t*)ptr;
116 ptr += 1;
117 alac->setinfo_rice_historymult = *(uint8_t*)ptr;
118 ptr += 1;
119 alac->setinfo_rice_initialhistory = *(uint8_t*)ptr;
120 ptr += 1;
121 alac->setinfo_rice_kmodifier = *(uint8_t*)ptr;
122 ptr += 1;
123 alac->setinfo_7f = *(uint8_t*)ptr;
124 ptr += 1;
125 alac->setinfo_80 = *(uint16_t*)ptr;
126 if (!host_bigendian)
127 _Swap16(alac->setinfo_80);
128 ptr += 2;
129 alac->setinfo_82 = *(uint32_t*)ptr;
130 if (!host_bigendian)
131 _Swap32(alac->setinfo_82);
132 ptr += 4;
133 alac->setinfo_86 = *(uint32_t*)ptr;
134 if (!host_bigendian)
135 _Swap32(alac->setinfo_86);
136 ptr += 4;
137 alac->setinfo_8a_rate = *(uint32_t*)ptr;
138 if (!host_bigendian)
139 _Swap32(alac->setinfo_8a_rate);
140 ptr += 4;
141
142 allocate_buffers(alac);
143
144}
145
146/* stream reading */
147
148/* supports reading 1 to 16 bits, in big endian format */
149static uint32_t readbits_16(alac_file *alac, int bits)
150{
151 uint32_t result;
152 int new_accumulator;
153
154 result = (alac->input_buffer[0] << 16) |
155 (alac->input_buffer[1] << 8) |
156 (alac->input_buffer[2]);
157
158 /* shift left by the number of bits we've already read,
159 * so that the top 'n' bits of the 24 bits we read will
160 * be the return bits */
161 result = result << alac->input_buffer_bitaccumulator;
162
163 result = result & 0x00ffffff;
164
165 /* and then only want the top 'n' bits from that, where
166 * n is 'bits' */
167 result = result >> (24 - bits);
168
169 new_accumulator = (alac->input_buffer_bitaccumulator + bits);
170
171 /* increase the buffer pointer if we've read over n bytes. */
172 alac->input_buffer += (new_accumulator >> 3);
173
174 /* and the remainder goes back into the bit accumulator */
175 alac->input_buffer_bitaccumulator = (new_accumulator & 7);
176
177 return result;
178}
179
180/* supports reading 1 to 32 bits, in big endian format */
181static uint32_t readbits(alac_file *alac, int bits)
182{
183 int32_t result = 0;
184
185 if (bits > 16)
186 {
187 bits -= 16;
188 result = readbits_16(alac, 16) << bits;
189 }
190
191 result |= readbits_16(alac, bits);
192
193 return result;
194}
195
196/* reads a single bit */
197static int readbit(alac_file *alac)
198{
199 int result;
200 int new_accumulator;
201
202 result = alac->input_buffer[0];
203
204 result = result << alac->input_buffer_bitaccumulator;
205
206 result = result >> 7 & 1;
207
208 new_accumulator = (alac->input_buffer_bitaccumulator + 1);
209
210 alac->input_buffer += (new_accumulator / 8);
211
212 alac->input_buffer_bitaccumulator = (new_accumulator % 8);
213
214 return result;
215}
216
217static void unreadbits(alac_file *alac, int bits)
218{
219 int new_accumulator = (alac->input_buffer_bitaccumulator - bits);
220
221 alac->input_buffer += (new_accumulator >> 3);
222
223 alac->input_buffer_bitaccumulator = (new_accumulator & 7);
224 if (alac->input_buffer_bitaccumulator < 0)
225 alac->input_buffer_bitaccumulator *= -1;
226}
227
228/* hideously inefficient. could use a bitmask search,
229 * alternatively bsr on x86,
230 */
231static int count_leading_zeros(int32_t input)
232{
233 int i = 0;
234 while (!(0x80000000 & input) && i < 32)
235 {
236 i++;
237 input = input << 1;
238 }
239 return i;
240}
241
242void basterdised_rice_decompress(alac_file *alac,
243 int32_t *output_buffer,
244 int output_size,
245 int readsamplesize, /* arg_10 */
246 int rice_initialhistory, /* arg424->b */
247 int rice_kmodifier, /* arg424->d */
248 int rice_historymult, /* arg424->c */
249 int rice_kmodifier_mask /* arg424->e */
250 )
251{
252 int output_count;
253 unsigned int history = rice_initialhistory;
254 int sign_modifier = 0;
255
256 for (output_count = 0; output_count < output_size; output_count++)
257 {
258 int32_t x = 0;
259 int32_t x_modified;
260 int32_t final_val;
261
262 /* read x - number of 1s before 0 represent the rice */
263 while (x <= 8 && readbit(alac))
264 {
265 x++;
266 }
267
268
269 if (x > 8) /* RICE THRESHOLD */
270 { /* use alternative encoding */
271 int32_t value;
272
273 value = readbits(alac, readsamplesize);
274
275 /* mask value to readsamplesize size */
276 if (readsamplesize != 32)
277 value &= (0xffffffff >> (32 - readsamplesize));
278
279 x = value;
280 }
281 else
282 { /* standard rice encoding */
283 int extrabits;
284 int k; /* size of extra bits */
285
286 /* read k, that is bits as is */
287 k = 31 - rice_kmodifier - count_leading_zeros((history >> 9) + 3);
288
289 if (k < 0) k += rice_kmodifier;
290 else k = rice_kmodifier;
291
292 if (k != 1)
293 {
294 extrabits = readbits(alac, k);
295
296 /* multiply x by 2^k - 1, as part of their strange algorithm */
297 x = (x << k) - x;
298
299 if (extrabits > 1)
300 {
301 x += extrabits - 1;
302 }
303 else unreadbits(alac, 1);
304 }
305 }
306
307 x_modified = sign_modifier + x;
308 final_val = (x_modified + 1) / 2;
309 if (x_modified & 1) final_val *= -1;
310
311 output_buffer[output_count] = final_val;
312
313 sign_modifier = 0;
314
315 /* now update the history */
316 history += (x_modified * rice_historymult)
317 - ((history * rice_historymult) >> 9);
318
319 if (x_modified > 0xffff)
320 history = 0xffff;
321
322 /* special case: there may be compressed blocks of 0 */
323 if ((history < 128) && (output_count+1 < output_size))
324 {
325 int block_size;
326
327 sign_modifier = 1;
328
329 x = 0;
330 while (x <= 8 && readbit(alac))
331 {
332 x++;
333 }
334
335 if (x > 8)
336 {
337 block_size = readbits(alac, 16);
338 block_size &= 0xffff;
339 }
340 else
341 {
342 int k;
343 int extrabits;
344
345 k = count_leading_zeros(history) + ((history + 16) >> 6 /* / 64 */) - 24;
346
347 extrabits = readbits(alac, k);
348
349 block_size = (((1 << k) - 1) & rice_kmodifier_mask) * x
350 + extrabits - 1;
351
352 if (extrabits < 2)
353 {
354 x = 1 - extrabits;
355 block_size += x;
356 unreadbits(alac, 1);
357 }
358 }
359
360 if (block_size > 0)
361 {
362 memset(&output_buffer[output_count+1], 0, block_size * 4);
363 output_count += block_size;
364
365 }
366
367 if (block_size > 0xffff)
368 sign_modifier = 0;
369
370 history = 0;
371 }
372 }
373}
374
375#define SIGN_EXTENDED32(val, bits) ((val << (32 - bits)) >> (32 - bits))
376
377#define SIGN_ONLY(v) \
378 ((v < 0) ? (-1) : \
379 ((v > 0) ? (1) : \
380 (0)))
381
382static void predictor_decompress_fir_adapt(int32_t *error_buffer,
383 int32_t *buffer_out,
384 int output_size,
385 int readsamplesize,
386 int16_t *predictor_coef_table,
387 int predictor_coef_num,
388 int predictor_quantitization)
389{
390 int i;
391
392 /* first sample always copies */
393 *buffer_out = *error_buffer;
394
395 if (!predictor_coef_num)
396 {
397 if (output_size <= 1) return;
398 memcpy(buffer_out+1, error_buffer+1, (output_size-1) * 4);
399 return;
400 }
401
402 if (predictor_coef_num == 0x1f) /* 11111 - max value of predictor_coef_num */
403 { /* second-best case scenario for fir decompression,
404 * error describes a small difference from the previous sample only
405 */
406 if (output_size <= 1) return;
407 for (i = 0; i < output_size - 1; i++)
408 {
409 int32_t prev_value;
410 int32_t error_value;
411
412 prev_value = buffer_out[i];
413 error_value = error_buffer[i+1];
414 buffer_out[i+1] = SIGN_EXTENDED32((prev_value + error_value), readsamplesize);
415 }
416 return;
417 }
418
419 /* read warm-up samples */
420 if (predictor_coef_num > 0)
421 {
422 int i;
423 for (i = 0; i < predictor_coef_num; i++)
424 {
425 int32_t val;
426
427 val = buffer_out[i] + error_buffer[i+1];
428
429 val = SIGN_EXTENDED32(val, readsamplesize);
430
431 buffer_out[i+1] = val;
432 }
433 }
434
435#if 0
436 /* 4 and 8 are very common cases (the only ones i've seen). these
437 * should be unrolled and optimised
438 */
439 if (predictor_coef_num == 4)
440 {
441 /* FIXME: optimised general case */
442 return;
443 }
444
445 if (predictor_coef_table == 8)
446 {
447 /* FIXME: optimised general case */
448 return;
449 }
450#endif
451
452
453 /* general case */
454 if (predictor_coef_num > 0)
455 {
456 for (i = predictor_coef_num + 1;
457 i < output_size;
458 i++)
459 {
460 int j;
461 int sum = 0;
462 int outval;
463 int error_val = error_buffer[i];
464
465 for (j = 0; j < predictor_coef_num; j++)
466 {
467 sum += (buffer_out[predictor_coef_num-j] - buffer_out[0]) *
468 predictor_coef_table[j];
469 }
470
471 outval = (1 << (predictor_quantitization-1)) + sum;
472 outval = outval >> predictor_quantitization;
473 outval = outval + buffer_out[0] + error_val;
474 outval = SIGN_EXTENDED32(outval, readsamplesize);
475
476 buffer_out[predictor_coef_num+1] = outval;
477
478 if (error_val > 0)
479 {
480 int predictor_num = predictor_coef_num - 1;
481
482 while (predictor_num >= 0 && error_val > 0)
483 {
484 int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num];
485 int sign = SIGN_ONLY(val);
486
487 predictor_coef_table[predictor_num] -= sign;
488
489 val *= sign; /* absolute value */
490
491 error_val -= ((val >> predictor_quantitization) *
492 (predictor_coef_num - predictor_num));
493
494 predictor_num--;
495 }
496 }
497 else if (error_val < 0)
498 {
499 int predictor_num = predictor_coef_num - 1;
500
501 while (predictor_num >= 0 && error_val < 0)
502 {
503 int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num];
504 int sign = - SIGN_ONLY(val);
505
506 predictor_coef_table[predictor_num] -= sign;
507
508 val *= sign; /* neg value */
509
510 error_val -= ((val >> predictor_quantitization) *
511 (predictor_coef_num - predictor_num));
512
513 predictor_num--;
514 }
515 }
516
517 buffer_out++;
518 }
519 }
520}
521
522void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
523 int16_t *buffer_out,
524 int numchannels, int numsamples,
525 uint8_t interlacing_shift,
526 uint8_t interlacing_leftweight)
527{
528 int i;
529 if (numsamples <= 0) return;
530
531 /* weighted interlacing */
532 if (interlacing_leftweight)
533 {
534 for (i = 0; i < numsamples; i++)
535 {
536 int32_t difference, midright;
537 int16_t left;
538 int16_t right;
539
540 midright = buffer_a[i];
541 difference = buffer_b[i];
542
543
544 right = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
545 left = (midright - ((difference * interlacing_leftweight) >> interlacing_shift))
546 + difference;
547
548 /* output is always little endian */
549 if (host_bigendian)
550 {
551 _Swap16(left);
552 _Swap16(right);
553 }
554
555 buffer_out[i*numchannels] = left;
556 buffer_out[i*numchannels + 1] = right;
557 }
558
559 return;
560 }
561
562 /* otherwise basic interlacing took place */
563 for (i = 0; i < numsamples; i++)
564 {
565 int16_t left, right;
566
567 left = buffer_a[i];
568 right = buffer_b[i];
569
570 /* output is always little endian */
571 if (host_bigendian)
572 {
573 _Swap16(left);
574 _Swap16(right);
575 }
576
577 buffer_out[i*numchannels] = left;
578 buffer_out[i*numchannels + 1] = right;
579 }
580}
581
582void decode_frame(alac_file *alac,
583 unsigned char *inbuffer,
584 void *outbuffer, int *outputsize)
585{
586 int channels;
587 int32_t outputsamples = alac->setinfo_max_samples_per_frame;
588
589 /* setup the stream */
590 alac->input_buffer = inbuffer;
591 alac->input_buffer_bitaccumulator = 0;
592
593 channels = readbits(alac, 3);
594
595 *outputsize = outputsamples * alac->bytespersample;
596
597 switch(channels)
598 {
599 case 0: /* 1 channel */
600 {
601 int hassize;
602 int isnotcompressed;
603 int readsamplesize;
604
605 int wasted_bytes;
606 int ricemodifier;
607
608
609 /* 2^result = something to do with output waiting.
610 * perhaps matters if we read > 1 frame in a pass?
611 */
612 readbits(alac, 4);
613
614 readbits(alac, 12); /* unknown, skip 12 bits */
615
616 hassize = readbits(alac, 1); /* the output sample size is stored soon */
617
618 wasted_bytes = readbits(alac, 2); /* unknown ? */
619
620 isnotcompressed = readbits(alac, 1); /* whether the frame is compressed */
621
622 if (hassize)
623 {
624 /* now read the number of samples,
625 * as a 32bit integer */
626 outputsamples = readbits(alac, 32);
627 *outputsize = outputsamples * alac->bytespersample;
628 }
629
630 readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8);
631
632 if (!isnotcompressed)
633 { /* so it is compressed */
634 int16_t predictor_coef_table[32];
635 int predictor_coef_num;
636 int prediction_type;
637 int prediction_quantitization;
638 int i;
639
640 /* skip 16 bits, not sure what they are. seem to be used in
641 * two channel case */
642 readbits(alac, 8);
643 readbits(alac, 8);
644
645 prediction_type = readbits(alac, 4);
646 prediction_quantitization = readbits(alac, 4);
647
648 ricemodifier = readbits(alac, 3);
649 predictor_coef_num = readbits(alac, 5);
650
651 /* read the predictor table */
652 for (i = 0; i < predictor_coef_num; i++)
653 {
654 predictor_coef_table[i] = (int16_t)readbits(alac, 16);
655 }
656
657 if (wasted_bytes)
658 {
659 /* these bytes seem to have something to do with
660 * > 2 channel files.
661 */
662 fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
663 }
664
665 basterdised_rice_decompress(alac,
666 alac->predicterror_buffer_a,
667 outputsamples,
668 readsamplesize,
669 alac->setinfo_rice_initialhistory,
670 alac->setinfo_rice_kmodifier,
671 ricemodifier * alac->setinfo_rice_historymult / 4,
672 (1 << alac->setinfo_rice_kmodifier) - 1);
673
674 if (prediction_type == 0)
675 { /* adaptive fir */
676 predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
677 alac->outputsamples_buffer_a,
678 outputsamples,
679 readsamplesize,
680 predictor_coef_table,
681 predictor_coef_num,
682 prediction_quantitization);
683 }
684 else
685 {
686 fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type);
687 /* i think the only other prediction type (or perhaps this is just a
688 * boolean?) runs adaptive fir twice.. like:
689 * predictor_decompress_fir_adapt(predictor_error, tempout, ...)
690 * predictor_decompress_fir_adapt(predictor_error, outputsamples ...)
691 * little strange..
692 */
693 }
694
695 }
696 else
697 { /* not compressed, easy case */
698 if (readsamplesize <= 16)
699 {
700 int i;
701 for (i = 0; i < outputsamples; i++)
702 {
703 int32_t audiobits = readbits(alac, readsamplesize);
704
705 audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);
706
707 alac->outputsamples_buffer_a[i] = audiobits;
708 }
709 }
710 else
711 {
712 int i;
713 for (i = 0; i < outputsamples; i++)
714 {
715 int32_t audiobits;
716
717 audiobits = readbits(alac, 16);
718 /* special case of sign extension..
719 * as we'll be ORing the low 16bits into this */
720 audiobits = audiobits << 16;
721 audiobits = audiobits >> (32 - readsamplesize);
722
723 audiobits |= readbits(alac, readsamplesize - 16);
724
725 alac->outputsamples_buffer_a[i] = audiobits;
726 }
727 }
728 /* wasted_bytes = 0; // unused */
729 }
730
731 switch(alac->setinfo_sample_size)
732 {
733 case 16:
734 {
735 int i;
736 for (i = 0; i < outputsamples; i++)
737 {
738 int16_t sample = alac->outputsamples_buffer_a[i];
739 if (host_bigendian)
740 _Swap16(sample);
741 ((int16_t*)outbuffer)[i * alac->numchannels] = sample;
742 }
743 break;
744 }
745 case 20:
746 case 24:
747 case 32:
748 fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
749 break;
750 default:
751 break;
752 }
753 break;
754 }
755 case 1: /* 2 channels */
756 {
757 int hassize;
758 int isnotcompressed;
759 int readsamplesize;
760
761 int wasted_bytes;
762
763 uint8_t interlacing_shift;
764 uint8_t interlacing_leftweight;
765
766 /* 2^result = something to do with output waiting.
767 * perhaps matters if we read > 1 frame in a pass?
768 */
769 readbits(alac, 4);
770
771 readbits(alac, 12); /* unknown, skip 12 bits */
772
773 hassize = readbits(alac, 1); /* the output sample size is stored soon */
774
775 wasted_bytes = readbits(alac, 2); /* unknown ? */
776
777 isnotcompressed = readbits(alac, 1); /* whether the frame is compressed */
778
779 if (hassize)
780 {
781 /* now read the number of samples,
782 * as a 32bit integer */
783 outputsamples = readbits(alac, 32);
784 *outputsize = outputsamples * alac->bytespersample;
785 }
786
787 readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8) + 1;
788
789 if (!isnotcompressed)
790 { /* compressed */
791 int16_t predictor_coef_table_a[32];
792 int predictor_coef_num_a;
793 int prediction_type_a;
794 int prediction_quantitization_a;
795 int ricemodifier_a;
796
797 int16_t predictor_coef_table_b[32];
798 int predictor_coef_num_b;
799 int prediction_type_b;
800 int prediction_quantitization_b;
801 int ricemodifier_b;
802
803 int i;
804
805 interlacing_shift = readbits(alac, 8);
806 interlacing_leftweight = readbits(alac, 8);
807
808 /******** channel 1 ***********/
809 prediction_type_a = readbits(alac, 4);
810 prediction_quantitization_a = readbits(alac, 4);
811
812 ricemodifier_a = readbits(alac, 3);
813 predictor_coef_num_a = readbits(alac, 5);
814
815 /* read the predictor table */
816 for (i = 0; i < predictor_coef_num_a; i++)
817 {
818 predictor_coef_table_a[i] = (int16_t)readbits(alac, 16);
819 }
820
821 /******** channel 2 *********/
822 prediction_type_b = readbits(alac, 4);
823 prediction_quantitization_b = readbits(alac, 4);
824
825 ricemodifier_b = readbits(alac, 3);
826 predictor_coef_num_b = readbits(alac, 5);
827
828 /* read the predictor table */
829 for (i = 0; i < predictor_coef_num_b; i++)
830 {
831 predictor_coef_table_b[i] = (int16_t)readbits(alac, 16);
832 }
833
834 /*********************/
835 if (wasted_bytes)
836 { /* see mono case */
837 fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
838 }
839
840 /* channel 1 */
841 basterdised_rice_decompress(alac,
842 alac->predicterror_buffer_a,
843 outputsamples,
844 readsamplesize,
845 alac->setinfo_rice_initialhistory,
846 alac->setinfo_rice_kmodifier,
847 ricemodifier_a * alac->setinfo_rice_historymult / 4,
848 (1 << alac->setinfo_rice_kmodifier) - 1);
849
850 if (prediction_type_a == 0)
851 { /* adaptive fir */
852 predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
853 alac->outputsamples_buffer_a,
854 outputsamples,
855 readsamplesize,
856 predictor_coef_table_a,
857 predictor_coef_num_a,
858 prediction_quantitization_a);
859 }
860 else
861 { /* see mono case */
862 fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a);
863 }
864
865 /* channel 2 */
866 basterdised_rice_decompress(alac,
867 alac->predicterror_buffer_b,
868 outputsamples,
869 readsamplesize,
870 alac->setinfo_rice_initialhistory,
871 alac->setinfo_rice_kmodifier,
872 ricemodifier_b * alac->setinfo_rice_historymult / 4,
873 (1 << alac->setinfo_rice_kmodifier) - 1);
874
875 if (prediction_type_b == 0)
876 { /* adaptive fir */
877 predictor_decompress_fir_adapt(alac->predicterror_buffer_b,
878 alac->outputsamples_buffer_b,
879 outputsamples,
880 readsamplesize,
881 predictor_coef_table_b,
882 predictor_coef_num_b,
883 prediction_quantitization_b);
884 }
885 else
886 {
887 fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b);
888 }
889 }
890 else
891 { /* not compressed, easy case */
892 if (alac->setinfo_sample_size <= 16)
893 {
894 int i;
895 for (i = 0; i < outputsamples; i++)
896 {
897 int32_t audiobits_a, audiobits_b;
898
899 audiobits_a = readbits(alac, alac->setinfo_sample_size);
900 audiobits_b = readbits(alac, alac->setinfo_sample_size);
901
902 audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);
903 audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);
904
905 alac->outputsamples_buffer_a[i] = audiobits_a;
906 alac->outputsamples_buffer_b[i] = audiobits_b;
907 }
908 }
909 else
910 {
911 int i;
912 for (i = 0; i < outputsamples; i++)
913 {
914 int32_t audiobits_a, audiobits_b;
915
916 audiobits_a = readbits(alac, 16);
917 audiobits_a = audiobits_a << 16;
918 audiobits_a = audiobits_a >> (32 - alac->setinfo_sample_size);
919 audiobits_a |= readbits(alac, alac->setinfo_sample_size - 16);
920
921 audiobits_b = readbits(alac, 16);
922 audiobits_b = audiobits_b << 16;
923 audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);
924 audiobits_b |= readbits(alac, alac->setinfo_sample_size - 16);
925
926 alac->outputsamples_buffer_a[i] = audiobits_a;
927 alac->outputsamples_buffer_b[i] = audiobits_b;
928 }
929 }
930 /* wasted_bytes = 0; */
931 interlacing_shift = 0;
932 interlacing_leftweight = 0;
933 }
934
935 switch(alac->setinfo_sample_size)
936 {
937 case 16:
938 {
939 deinterlace_16(alac->outputsamples_buffer_a,
940 alac->outputsamples_buffer_b,
941 (int16_t*)outbuffer,
942 alac->numchannels,
943 outputsamples,
944 interlacing_shift,
945 interlacing_leftweight);
946 break;
947 }
948 case 20:
949 case 24:
950 case 32:
951 fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
952 break;
953 default:
954 break;
955 }
956
957 break;
958 }
959 }
960}
961
962alac_file *create_alac(int samplesize, int numchannels)
963{
964 alac_file *newfile = malloc(sizeof(alac_file));
965
966 newfile->samplesize = samplesize;
967 newfile->numchannels = numchannels;
968 newfile->bytespersample = (samplesize / 8) * numchannels;
969
970 return newfile;
971}
972
diff --git a/apps/codecs/libalac/decomp.h b/apps/codecs/libalac/decomp.h
new file mode 100644
index 0000000000..23dbc52779
--- /dev/null
+++ b/apps/codecs/libalac/decomp.h
@@ -0,0 +1,13 @@
1#ifndef __ALAC__DECOMP_H
2#define __ALAC__DECOMP_H
3
4typedef struct alac_file alac_file;
5
6alac_file *create_alac(int samplesize, int numchannels);
7void decode_frame(alac_file *alac,
8 unsigned char *inbuffer,
9 void *outbuffer, int *outputsize);
10void alac_set_info(alac_file *alac, char *inputbuffer);
11
12#endif /* __ALAC__DECOMP_H */
13
diff --git a/apps/codecs/libalac/demux.c b/apps/codecs/libalac/demux.c
new file mode 100644
index 0000000000..7263a763d4
--- /dev/null
+++ b/apps/codecs/libalac/demux.c
@@ -0,0 +1,637 @@
1/*
2 * ALAC (Apple Lossless Audio Codec) decoder
3 * Copyright (c) 2005 David Hammerton
4 * All rights reserved.
5 *
6 * This is the quicktime container demuxer.
7 *
8 * http://crazney.net/programs/itunes/alac.html
9 *
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated documentation
12 * files (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use,
14 * copy, modify, merge, publish, distribute, sublicense, and/or
15 * sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 *
30 */
31
32
33#include <string.h>
34#include <stdio.h>
35#include <stdint.h>
36#include <stdlib.h>
37
38#include "stream.h"
39#include "demux.h"
40
41typedef struct
42{
43 stream_t *stream;
44 demux_res_t *res;
45} qtmovie_t;
46
47
48/* chunk handlers */
49static void read_chunk_ftyp(qtmovie_t *qtmovie, size_t chunk_len)
50{
51 fourcc_t type;
52 uint32_t minor_ver;
53 size_t size_remaining = chunk_len - 8; /* FIXME: can't hardcode 8, size may be 64bit */
54
55 type = stream_read_uint32(qtmovie->stream);
56 size_remaining-=4;
57 if (type != MAKEFOURCC('M','4','A',' '))
58 {
59 fprintf(stderr, "not M4A file\n");
60 return;
61 }
62 minor_ver = stream_read_uint32(qtmovie->stream);
63 size_remaining-=4;
64
65 /* compatible brands */
66 while (size_remaining)
67 {
68 /* unused */
69 /*fourcc_t cbrand =*/ stream_read_uint32(qtmovie->stream);
70 size_remaining-=4;
71 }
72}
73
74static void read_chunk_tkhd(qtmovie_t *qtmovie, size_t chunk_len)
75{
76 /* don't need anything from here atm, skip */
77 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
78
79 stream_skip(qtmovie->stream, size_remaining);
80}
81
82static void read_chunk_mdhd(qtmovie_t *qtmovie, size_t chunk_len)
83{
84 /* don't need anything from here atm, skip */
85 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
86
87 stream_skip(qtmovie->stream, size_remaining);
88}
89
90/* media handler inside mdia */
91static void read_chunk_hdlr(qtmovie_t *qtmovie, size_t chunk_len)
92{
93 fourcc_t comptype, compsubtype;
94 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
95
96 int strlen;
97 char str[256] = {0};
98
99 /* version */
100 stream_read_uint8(qtmovie->stream);
101 size_remaining -= 1;
102 /* flags */
103 stream_read_uint8(qtmovie->stream);
104 stream_read_uint8(qtmovie->stream);
105 stream_read_uint8(qtmovie->stream);
106 size_remaining -= 3;
107
108 /* component type */
109 comptype = stream_read_uint32(qtmovie->stream);
110 compsubtype = stream_read_uint32(qtmovie->stream);
111 size_remaining -= 8;
112
113 /* component manufacturer */
114 stream_read_uint32(qtmovie->stream);
115 size_remaining -= 4;
116
117 /* flags */
118 stream_read_uint32(qtmovie->stream);
119 stream_read_uint32(qtmovie->stream);
120 size_remaining -= 8;
121
122 /* name */
123 strlen = stream_read_uint8(qtmovie->stream);
124 stream_read(qtmovie->stream, strlen, str);
125 size_remaining -= 1 + strlen;
126
127 if (size_remaining)
128 {
129 stream_skip(qtmovie->stream, size_remaining);
130 }
131
132}
133
134static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
135{
136 unsigned int i;
137 uint32_t numentries;
138 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
139
140 /* version */
141 stream_read_uint8(qtmovie->stream);
142 size_remaining -= 1;
143 /* flags */
144 stream_read_uint8(qtmovie->stream);
145 stream_read_uint8(qtmovie->stream);
146 stream_read_uint8(qtmovie->stream);
147 size_remaining -= 3;
148
149 numentries = stream_read_uint32(qtmovie->stream);
150 size_remaining -= 4;
151
152 if (numentries != 1)
153 {
154 fprintf(stderr, "only expecting one entry in sample description atom!\n");
155 return;
156 }
157
158 for (i = 0; i < numentries; i++)
159 {
160 uint32_t entry_size;
161 uint16_t version;
162
163 uint32_t entry_remaining;
164
165 entry_size = stream_read_uint32(qtmovie->stream);
166 qtmovie->res->format = stream_read_uint32(qtmovie->stream);
167 entry_remaining = entry_size;
168 entry_remaining -= 8;
169
170 /* sound info: */
171
172 stream_skip(qtmovie->stream, 6); /* reserved */
173 entry_remaining -= 6;
174
175 version = stream_read_uint16(qtmovie->stream);
176 if (version != 1)
177 fprintf(stderr, "unknown version??\n");
178 entry_remaining -= 2;
179
180 /* revision level */
181 stream_read_uint16(qtmovie->stream);
182 /* vendor */
183 stream_read_uint32(qtmovie->stream);
184 entry_remaining -= 6;
185
186 /* EH?? spec doesn't say theres an extra 16 bits here.. but there is! */
187 stream_read_uint16(qtmovie->stream);
188 entry_remaining -= 2;
189
190 qtmovie->res->num_channels = stream_read_uint16(qtmovie->stream);
191
192 qtmovie->res->sample_size = stream_read_uint16(qtmovie->stream);
193 entry_remaining -= 4;
194
195 /* compression id */
196 stream_read_uint16(qtmovie->stream);
197 /* packet size */
198 stream_read_uint16(qtmovie->stream);
199 entry_remaining -= 4;
200
201 /* sample rate - 32bit fixed point = 16bit?? */
202 qtmovie->res->sample_rate = stream_read_uint16(qtmovie->stream);
203 entry_remaining -= 2;
204
205 /* skip 2 */
206 stream_skip(qtmovie->stream, 2);
207 entry_remaining -= 2;
208
209 /* remaining is codec data */
210
211#if 0
212 qtmovie->res->codecdata_len = stream_read_uint32(qtmovie->stream);
213 if (qtmovie->res->codecdata_len != entry_remaining)
214 fprintf(stderr, "perhaps not? %i vs %i\n",
215 qtmovie->res->codecdata_len, entry_remaining);
216 entry_remaining -= 4;
217 stream_read_uint32(qtmovie->stream); /* 'alac' */
218 entry_remaining -= 4;
219
220 qtmovie->res->codecdata = malloc(qtmovie->res->codecdata_len - 8);
221
222 stream_read(qtmovie->stream,
223 entry_remaining,
224 qtmovie->res->codecdata);
225 entry_remaining = 0;
226
227#else
228 /* 12 = audio format atom, 8 = padding */
229 qtmovie->res->codecdata_len = entry_remaining + 12 + 8;
230 qtmovie->res->codecdata = malloc(qtmovie->res->codecdata_len);
231 memset(qtmovie->res->codecdata, 0, qtmovie->res->codecdata_len);
232 /* audio format atom */
233 ((unsigned int*)qtmovie->res->codecdata)[0] = 0x0c000000;
234 ((unsigned int*)qtmovie->res->codecdata)[1] = MAKEFOURCC('a','m','r','f');
235 ((unsigned int*)qtmovie->res->codecdata)[2] = MAKEFOURCC('c','a','l','a');
236
237 stream_read(qtmovie->stream,
238 entry_remaining,
239 ((char*)qtmovie->res->codecdata) + 12);
240 entry_remaining -= entry_remaining;
241
242#endif
243 if (entry_remaining)
244 stream_skip(qtmovie->stream, entry_remaining);
245
246 if (qtmovie->res->format != MAKEFOURCC('a','l','a','c'))
247 {
248 fprintf(stderr, "expecting 'alac' data format, got %c%c%c%c\n",
249 SPLITFOURCC(qtmovie->res->format));
250 return;
251 }
252 }
253}
254
255static void read_chunk_stts(qtmovie_t *qtmovie, size_t chunk_len)
256{
257 unsigned int i;
258 uint32_t numentries;
259 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
260
261 /* version */
262 stream_read_uint8(qtmovie->stream);
263 size_remaining -= 1;
264 /* flags */
265 stream_read_uint8(qtmovie->stream);
266 stream_read_uint8(qtmovie->stream);
267 stream_read_uint8(qtmovie->stream);
268 size_remaining -= 3;
269
270 numentries = stream_read_uint32(qtmovie->stream);
271 size_remaining -= 4;
272
273 qtmovie->res->num_time_to_samples = numentries;
274 qtmovie->res->time_to_sample = malloc(numentries * sizeof(*qtmovie->res->time_to_sample));
275
276 for (i = 0; i < numentries; i++)
277 {
278 qtmovie->res->time_to_sample[i].sample_count = stream_read_uint32(qtmovie->stream);
279 qtmovie->res->time_to_sample[i].sample_duration = stream_read_uint32(qtmovie->stream);
280 size_remaining -= 8;
281 }
282
283 if (size_remaining)
284 {
285 fprintf(stderr, "ehm, size remianing?\n");
286 stream_skip(qtmovie->stream, size_remaining);
287 }
288}
289
290static void read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
291{
292 unsigned int i;
293 uint32_t numentries;
294 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
295
296 /* version */
297 stream_read_uint8(qtmovie->stream);
298 size_remaining -= 1;
299 /* flags */
300 stream_read_uint8(qtmovie->stream);
301 stream_read_uint8(qtmovie->stream);
302 stream_read_uint8(qtmovie->stream);
303 size_remaining -= 3;
304
305 /* default sample size */
306 if (stream_read_uint32(qtmovie->stream) != 0)
307 {
308 fprintf(stderr, "i was expecting variable samples sizes\n");
309 stream_read_uint32(qtmovie->stream);
310 size_remaining -= 4;
311 return;
312 }
313 size_remaining -= 4;
314
315 numentries = stream_read_uint32(qtmovie->stream);
316 size_remaining -= 4;
317
318 qtmovie->res->num_sample_byte_sizes = numentries;
319 qtmovie->res->sample_byte_size = malloc(numentries * sizeof(*qtmovie->res->sample_byte_size));
320
321 for (i = 0; i < numentries; i++)
322 {
323 qtmovie->res->sample_byte_size[i] = stream_read_uint32(qtmovie->stream);
324 size_remaining -= 4;
325 }
326
327 if (size_remaining)
328 {
329 fprintf(stderr, "ehm, size remianing?\n");
330 stream_skip(qtmovie->stream, size_remaining);
331 }
332}
333
334static void read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
335{
336 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
337
338 while (size_remaining)
339 {
340 size_t sub_chunk_len;
341 fourcc_t sub_chunk_id;
342
343 sub_chunk_len = stream_read_uint32(qtmovie->stream);
344 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
345 {
346 fprintf(stderr, "strange size for chunk inside stbl\n");
347 return;
348 }
349
350 sub_chunk_id = stream_read_uint32(qtmovie->stream);
351
352 switch (sub_chunk_id)
353 {
354 case MAKEFOURCC('s','t','s','d'):
355 read_chunk_stsd(qtmovie, sub_chunk_len);
356 break;
357 case MAKEFOURCC('s','t','t','s'):
358 read_chunk_stts(qtmovie, sub_chunk_len);
359 break;
360 case MAKEFOURCC('s','t','s','z'):
361 read_chunk_stsz(qtmovie, sub_chunk_len);
362 break;
363 case MAKEFOURCC('s','t','s','c'):
364 case MAKEFOURCC('s','t','c','o'):
365 /* skip these, no indexing for us! */
366 stream_skip(qtmovie->stream, sub_chunk_len - 8);
367 break;
368 default:
369 fprintf(stderr, "(stbl) unknown chunk id: %c%c%c%c\n",
370 SPLITFOURCC(sub_chunk_id));
371 return;
372 }
373
374 size_remaining -= sub_chunk_len;
375 }
376}
377
378static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
379{
380 size_t dinf_size, stbl_size;
381 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
382
383 /**** SOUND HEADER CHUNK ****/
384 if (stream_read_uint32(qtmovie->stream) != 16)
385 {
386 fprintf(stderr, "unexpected size in media info\n");
387 return;
388 }
389 if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','m','h','d'))
390 {
391 fprintf(stderr, "not a sound header! can't handle this.\n");
392 return;
393 }
394 /* now skip the rest */
395 stream_skip(qtmovie->stream, 16 - 8);
396 size_remaining -= 16;
397 /****/
398
399 /**** DINF CHUNK ****/
400 dinf_size = stream_read_uint32(qtmovie->stream);
401 if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('d','i','n','f'))
402 {
403 fprintf(stderr, "expected dinf, didn't get it.\n");
404 return;
405 }
406 /* skip it */
407 stream_skip(qtmovie->stream, dinf_size - 8);
408 size_remaining -= dinf_size;
409 /****/
410
411
412 /**** SAMPLE TABLE ****/
413 stbl_size = stream_read_uint32(qtmovie->stream);
414 if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','t','b','l'))
415 {
416 fprintf(stderr, "expected stbl, didn't get it.\n");
417 return;
418 }
419 read_chunk_stbl(qtmovie, stbl_size);
420 size_remaining -= stbl_size;
421
422 if (size_remaining)
423 {
424 fprintf(stderr, "oops\n");
425 stream_skip(qtmovie->stream, size_remaining);
426 }
427}
428
429static void read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
430{
431 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
432
433 while (size_remaining)
434 {
435 size_t sub_chunk_len;
436 fourcc_t sub_chunk_id;
437
438 sub_chunk_len = stream_read_uint32(qtmovie->stream);
439 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
440 {
441 fprintf(stderr, "strange size for chunk inside mdia\n");
442 return;
443 }
444
445 sub_chunk_id = stream_read_uint32(qtmovie->stream);
446
447 switch (sub_chunk_id)
448 {
449 case MAKEFOURCC('m','d','h','d'):
450 read_chunk_mdhd(qtmovie, sub_chunk_len);
451 break;
452 case MAKEFOURCC('h','d','l','r'):
453 read_chunk_hdlr(qtmovie, sub_chunk_len);
454 break;
455 case MAKEFOURCC('m','i','n','f'):
456 read_chunk_minf(qtmovie, sub_chunk_len);
457 break;
458 default:
459 fprintf(stderr, "(mdia) unknown chunk id: %c%c%c%c\n",
460 SPLITFOURCC(sub_chunk_id));
461 return;
462 }
463
464 size_remaining -= sub_chunk_len;
465 }
466}
467
468/* 'trak' - a movie track - contains other atoms */
469static void read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
470{
471 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
472
473 while (size_remaining)
474 {
475 size_t sub_chunk_len;
476 fourcc_t sub_chunk_id;
477
478 sub_chunk_len = stream_read_uint32(qtmovie->stream);
479 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
480 {
481 fprintf(stderr, "strange size for chunk inside trak\n");
482 return;
483 }
484
485 sub_chunk_id = stream_read_uint32(qtmovie->stream);
486
487 switch (sub_chunk_id)
488 {
489 case MAKEFOURCC('t','k','h','d'):
490 read_chunk_tkhd(qtmovie, sub_chunk_len);
491 break;
492 case MAKEFOURCC('m','d','i','a'):
493 read_chunk_mdia(qtmovie, sub_chunk_len);
494 break;
495 default:
496 fprintf(stderr, "(trak) unknown chunk id: %c%c%c%c\n",
497 SPLITFOURCC(sub_chunk_id));
498 return;
499 }
500
501 size_remaining -= sub_chunk_len;
502 }
503}
504
505/* 'mvhd' movie header atom */
506static void read_chunk_mvhd(qtmovie_t *qtmovie, size_t chunk_len)
507{
508 /* don't need anything from here atm, skip */
509 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
510
511 stream_skip(qtmovie->stream, size_remaining);
512}
513
514/* 'udta' user data.. contains tag info */
515static void read_chunk_udta(qtmovie_t *qtmovie, size_t chunk_len)
516{
517 /* don't need anything from here atm, skip */
518 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
519
520 stream_skip(qtmovie->stream, size_remaining);
521}
522
523/* 'moov' movie atom - contains other atoms */
524static void read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
525{
526 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
527
528 while (size_remaining)
529 {
530 size_t sub_chunk_len;
531 fourcc_t sub_chunk_id;
532
533 sub_chunk_len = stream_read_uint32(qtmovie->stream);
534 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
535 {
536 fprintf(stderr, "strange size for chunk inside moov\n");
537 return;
538 }
539
540 sub_chunk_id = stream_read_uint32(qtmovie->stream);
541
542 switch (sub_chunk_id)
543 {
544 case MAKEFOURCC('m','v','h','d'):
545 read_chunk_mvhd(qtmovie, sub_chunk_len);
546 break;
547 case MAKEFOURCC('t','r','a','k'):
548 read_chunk_trak(qtmovie, sub_chunk_len);
549 break;
550 case MAKEFOURCC('u','d','t','a'):
551 read_chunk_udta(qtmovie, sub_chunk_len);
552 break;
553 default:
554 fprintf(stderr, "(moov) unknown chunk id: %c%c%c%c\n",
555 SPLITFOURCC(sub_chunk_id));
556 return;
557 }
558
559 size_remaining -= sub_chunk_len;
560 }
561}
562
563static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len)
564{
565 size_t size_remaining = chunk_len - 8; /* FIXME WRONG */
566
567 qtmovie->res->mdat_len = size_remaining;
568#if 0
569 qtmovie->res->mdat = malloc(size_remaining);
570
571 stream_read(qtmovie->stream, size_remaining, qtmovie->res->mdat);
572#endif
573}
574
575int qtmovie_read(stream_t *file, demux_res_t *demux_res)
576{
577 qtmovie_t *qtmovie;
578
579 qtmovie = (qtmovie_t*)malloc(sizeof(qtmovie_t));
580
581 /* construct the stream */
582 qtmovie->stream = file;
583
584 qtmovie->res = demux_res;
585
586 /* read the chunks */
587 while (1)
588 {
589 size_t chunk_len;
590 fourcc_t chunk_id;
591
592 chunk_len = stream_read_uint32(qtmovie->stream);
593 if (stream_eof(qtmovie->stream))
594 {
595 return 0;
596 }
597
598 if (chunk_len == 1)
599 {
600 fprintf(stderr, "need 64bit support\n");
601 return 0;
602 }
603 chunk_id = stream_read_uint32(qtmovie->stream);
604
605 switch (chunk_id)
606 {
607 case MAKEFOURCC('f','t','y','p'):
608 read_chunk_ftyp(qtmovie, chunk_len);
609 break;
610 case MAKEFOURCC('m','o','o','v'):
611 read_chunk_moov(qtmovie, chunk_len);
612 break;
613 /* once we hit mdat we stop reading and return.
614 * this is on the assumption that there is no furhter interesting
615 * stuff in the stream. if there is stuff will fail (:()).
616 * But we need the read pointer to be at the mdat stuff
617 * for the decoder. And we don't want to rely on fseek/ftell,
618 * as they may not always be avilable */
619 case MAKEFOURCC('m','d','a','t'):
620 read_chunk_mdat(qtmovie, chunk_len);
621 return 1;
622
623 /* these following atoms can be skipped !!!! */
624 case MAKEFOURCC('f','r','e','e'):
625 stream_skip(qtmovie->stream, chunk_len - 8); /* FIXME not 8 */
626 break;
627 default:
628 fprintf(stderr, "(top) unknown chunk id: %c%c%c%c\n",
629 SPLITFOURCC(chunk_id));
630 return 0;
631 }
632
633 }
634 return 0;
635}
636
637
diff --git a/apps/codecs/libalac/demux.h b/apps/codecs/libalac/demux.h
new file mode 100644
index 0000000000..62b949fa3b
--- /dev/null
+++ b/apps/codecs/libalac/demux.h
@@ -0,0 +1,55 @@
1#ifndef DEMUX_H
2#define DEMUX_H
3
4#include <stdint.h>
5#include "stream.h"
6
7typedef uint32_t fourcc_t;
8
9typedef struct
10{
11 uint16_t num_channels;
12 uint16_t sample_size;
13 uint32_t sample_rate;
14 fourcc_t format;
15 void *buf;
16
17 struct {
18 uint32_t sample_count;
19 uint32_t sample_duration;
20 } *time_to_sample;
21 uint32_t num_time_to_samples;
22
23 uint32_t *sample_byte_size;
24 uint32_t num_sample_byte_sizes;
25
26 uint32_t codecdata_len;
27 void *codecdata;
28
29 uint32_t mdat_len;
30#if 0
31 void *mdat;
32#endif
33} demux_res_t;
34
35int qtmovie_read(stream_t *stream, demux_res_t *demux_res);
36
37#ifndef MAKEFOURCC
38#define MAKEFOURCC(ch0, ch1, ch2, ch3) ( \
39 ( (int32_t)(char)(ch0) << 24 ) | \
40 ( (int32_t)(char)(ch1) << 16 ) | \
41 ( (int32_t)(char)(ch2) << 8 ) | \
42 ( (int32_t)(char)(ch3) ) )
43#endif
44
45#ifndef SLPITFOURCC
46/* splits it into ch0, ch1, ch2, ch3 - use for printf's */
47#define SPLITFOURCC(code) \
48 (char)((int32_t)code >> 24), \
49 (char)((int32_t)code >> 16), \
50 (char)((int32_t)code >> 8), \
51 (char)code
52#endif
53
54#endif /* DEMUX_H */
55
diff --git a/apps/codecs/libalac/stream.h b/apps/codecs/libalac/stream.h
new file mode 100644
index 0000000000..31f93d9059
--- /dev/null
+++ b/apps/codecs/libalac/stream.h
@@ -0,0 +1,30 @@
1#ifndef STREAM_H
2#define STREAM_H
3
4/* stream.h */
5
6#include <stdint.h>
7
8typedef struct stream_tTAG stream_t;
9
10void stream_read(stream_t *stream, size_t len, void *buf);
11
12int32_t stream_read_int32(stream_t *stream);
13uint32_t stream_read_uint32(stream_t *stream);
14
15int16_t stream_read_int16(stream_t *stream);
16uint16_t stream_read_uint16(stream_t *stream);
17
18int8_t stream_read_int8(stream_t *stream);
19uint8_t stream_read_uint8(stream_t *stream);
20
21void stream_skip(stream_t *stream, size_t skip);
22
23int stream_eof(stream_t *stream);
24
25stream_t *stream_create_file(FILE *file,
26 int bigendian);
27void stream_destroy(stream_t *stream);
28
29#endif /* STREAM_H */
30