diff options
Diffstat (limited to 'apps/codecs/libalac/demux.c')
-rw-r--r-- | apps/codecs/libalac/demux.c | 637 |
1 files changed, 637 insertions, 0 deletions
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 | |||
41 | typedef struct | ||
42 | { | ||
43 | stream_t *stream; | ||
44 | demux_res_t *res; | ||
45 | } qtmovie_t; | ||
46 | |||
47 | |||
48 | /* chunk handlers */ | ||
49 | static 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 | |||
74 | static 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 | |||
82 | static 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 */ | ||
91 | static 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 | |||
134 | static 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 | |||
255 | static 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 | |||
290 | static 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 | |||
334 | static 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 | |||
378 | static 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 | |||
429 | static 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 */ | ||
469 | static 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 */ | ||
506 | static 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 */ | ||
515 | static 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 */ | ||
524 | static 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 | |||
563 | static 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 | |||
575 | int 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 | |||