Convert many #ifdef SIMULATOR to #if (CONFIG_PLATFORM & PLATFORM_HOSTED) (and similar).
[kugel-rb.git] / apps / codecs / libm4a / demux.c
blobea13fbeb9be28b059d46dd7a445fafaacf468967
1 /*
2 * ALAC (Apple Lossless Audio Codec) decoder
3 * Copyright (c) 2005 David Hammerton
4 * All rights reserved.
6 * This is the quicktime container demuxer.
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:
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
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.
32 #include <string.h>
33 #include <inttypes.h>
34 #include <stdlib.h>
36 #include "codeclib.h"
38 #include "m4a.h"
40 #if defined(DEBUG) || (CONFIG_PLATFORM & PLATFORM_HOSTED)
41 #ifdef DEBUGF
42 #undef DEBUGF
43 #endif
44 #define DEBUGF qtmovie->stream->ci->debugf
45 #else
46 #define DEBUGF(...)
47 #endif
49 typedef struct
51 stream_t *stream;
52 demux_res_t *res;
53 } qtmovie_t;
56 /* chunk handlers */
57 static void read_chunk_ftyp(qtmovie_t *qtmovie, size_t chunk_len)
59 fourcc_t type;
60 uint32_t minor_ver;
61 size_t size_remaining = chunk_len - 8;
63 type = stream_read_uint32(qtmovie->stream);
64 size_remaining-=4;
65 if ((type != MAKEFOURCC('M','4','A',' ')) &&
66 (type != MAKEFOURCC('M','4','B',' ')) &&
67 (type != MAKEFOURCC('m','p','4','2')) &&
68 (type != MAKEFOURCC('3','g','p','6')) &&
69 (type != MAKEFOURCC('q','t',' ',' ')) &&
70 (type != MAKEFOURCC('i','s','o','m')))
72 DEBUGF("not M4A file\n");
73 return;
75 minor_ver = stream_read_uint32(qtmovie->stream);
76 size_remaining-=4;
78 /* compatible brands */
79 while (size_remaining)
81 /* unused */
82 /*fourcc_t cbrand =*/ stream_read_uint32(qtmovie->stream);
83 size_remaining-=4;
87 static uint32_t mp4ff_read_mp4_descr_length(stream_t* stream)
89 uint8_t b;
90 uint8_t numBytes = 0;
91 uint32_t length = 0;
95 b = stream_read_uint8(stream);
96 numBytes++;
97 length = (length << 7) | (b & 0x7F);
98 } while ((b & 0x80) && numBytes < 4);
100 return length;
103 /* The following function is based on mp4ff */
104 static bool read_chunk_esds(qtmovie_t *qtmovie, size_t chunk_len)
106 uint8_t tag;
107 uint32_t temp;
108 int audioType;
109 int32_t maxBitrate;
110 int32_t avgBitrate;
112 (void)chunk_len;
113 /* version and flags */
114 temp=stream_read_uint32(qtmovie->stream);
116 /* get and verify ES_DescrTag */
117 tag = stream_read_uint8(qtmovie->stream);
118 if (tag == 0x03)
120 /* read length */
121 if (mp4ff_read_mp4_descr_length(qtmovie->stream) < 5 + 15)
123 return false;
125 /* skip 3 bytes */
126 stream_skip(qtmovie->stream,3);
127 } else {
128 /* skip 2 bytes */
129 stream_skip(qtmovie->stream,2);
132 /* get and verify DecoderConfigDescrTab */
133 if (stream_read_uint8(qtmovie->stream) != 0x04)
135 return false;
138 /* read length */
139 temp = mp4ff_read_mp4_descr_length(qtmovie->stream);
140 if (temp < 13) return false;
142 audioType = stream_read_uint8(qtmovie->stream);
143 temp=stream_read_int32(qtmovie->stream);//0x15000414 ????
144 maxBitrate = stream_read_int32(qtmovie->stream);
145 avgBitrate = stream_read_int32(qtmovie->stream);
146 DEBUGF("audioType=%d, maxBitrate=%ld, avgBitrate=%ld\n",audioType,
147 (long)maxBitrate,(long)avgBitrate);
149 /* get and verify DecSpecificInfoTag */
150 if (stream_read_uint8(qtmovie->stream) != 0x05)
152 return false;
155 /* read length */
156 qtmovie->res->codecdata_len = mp4ff_read_mp4_descr_length(qtmovie->stream);
157 if (qtmovie->res->codecdata_len > MAX_CODECDATA_SIZE)
159 DEBUGF("codecdata too large (%d) in esds\n",
160 (int)qtmovie->res->codecdata_len);
161 return false;
164 stream_read(qtmovie->stream, qtmovie->res->codecdata_len, qtmovie->res->codecdata);
166 /* will skip the remainder of the atom */
167 return true;
170 static bool read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
172 unsigned int i;
173 int j;
174 uint32_t numentries;
175 size_t size_remaining = chunk_len - 8;
177 /* version */
178 stream_read_uint8(qtmovie->stream);
179 size_remaining -= 1;
180 /* flags */
181 stream_read_uint8(qtmovie->stream);
182 stream_read_uint8(qtmovie->stream);
183 stream_read_uint8(qtmovie->stream);
184 size_remaining -= 3;
186 numentries = stream_read_uint32(qtmovie->stream);
187 size_remaining -= 4;
189 if (numentries != 1)
191 DEBUGF("only expecting one entry in sample description atom!\n");
192 return false;
195 for (i = 0; i < numentries; i++)
197 uint32_t entry_size;
199 uint32_t entry_remaining;
201 entry_size = stream_read_uint32(qtmovie->stream);
202 qtmovie->res->format = stream_read_uint32(qtmovie->stream);
203 DEBUGF("format: %c%c%c%c\n",SPLITFOURCC(qtmovie->res->format));
204 entry_remaining = entry_size;
205 entry_remaining -= 8;
207 /* sound info: */
209 /* reserved + data reference index + sound version + reserved */
210 stream_skip(qtmovie->stream, 6 + 2 + 2 + 6);
211 entry_remaining -= 6 + 2 + 2 + 6;
213 qtmovie->res->num_channels = stream_read_uint16(qtmovie->stream);
214 qtmovie->res->sound_sample_size = stream_read_uint16(qtmovie->stream);
215 entry_remaining -= 4;
217 /* packet size */
218 stream_skip(qtmovie->stream, 2);
219 qtmovie->res->sound_sample_rate = stream_read_uint32(qtmovie->stream);
220 /* reserved size */
221 stream_skip(qtmovie->stream, 2);
222 entry_remaining -= 8;
224 /* remaining is codec data */
226 if ((qtmovie->res->format==MAKEFOURCC('a','l','a','c'))) {
227 if (qtmovie->stream->ci->id3->codectype!=AFMT_MP4_ALAC) {
228 return false;
231 /* 12 = audio format atom, 8 = padding */
232 qtmovie->res->codecdata_len = entry_remaining + 12 + 8;
233 if (qtmovie->res->codecdata_len > MAX_CODECDATA_SIZE)
235 DEBUGF("codecdata too large (%d) in stsd\n",
236 (int)qtmovie->res->codecdata_len);
237 return false;
240 memset(qtmovie->res->codecdata, 0, qtmovie->res->codecdata_len);
241 /* audio format atom */
242 #if 0
243 /* The ALAC decoder skips these bytes, so there is no need to store them,
244 and this code isn't endian/alignment safe */
245 ((unsigned int*)qtmovie->res->codecdata)[0] = 0x0c000000;
246 ((unsigned int*)qtmovie->res->codecdata)[1] = MAKEFOURCC('a','m','r','f');
247 ((unsigned int*)qtmovie->res->codecdata)[2] = MAKEFOURCC('c','a','l','a');
248 #endif
250 stream_read(qtmovie->stream,
251 entry_remaining,
252 ((char*)qtmovie->res->codecdata) + 12);
253 entry_remaining -= entry_remaining;
255 if (entry_remaining)
256 stream_skip(qtmovie->stream, entry_remaining);
258 } else if (qtmovie->res->format==MAKEFOURCC('m','p','4','a')) {
259 if (qtmovie->stream->ci->id3->codectype!=AFMT_MP4_AAC) {
260 return false;
263 size_t sub_chunk_len;
264 fourcc_t sub_chunk_id;
266 sub_chunk_len = stream_read_uint32(qtmovie->stream);
267 if (sub_chunk_len <= 1 || sub_chunk_len > entry_remaining)
269 DEBUGF("strange size (%lu) for chunk inside mp4a\n",
270 (unsigned long)sub_chunk_len);
271 return false;
274 sub_chunk_id = stream_read_uint32(qtmovie->stream);
276 if (sub_chunk_id != MAKEFOURCC('e','s','d','s'))
278 DEBUGF("Expected esds chunk inside mp4a, found %c%c%c%c\n",SPLITFOURCC(sub_chunk_id));
279 return false;
282 j=qtmovie->stream->ci->curpos+sub_chunk_len-8;
283 if (read_chunk_esds(qtmovie,sub_chunk_len)) {
284 if (j!=qtmovie->stream->ci->curpos) {
285 DEBUGF("curpos=%ld, j=%d - Skipping %ld bytes\n",qtmovie->stream->ci->curpos,j,j-qtmovie->stream->ci->curpos);
286 stream_skip(qtmovie->stream,j-qtmovie->stream->ci->curpos);
288 entry_remaining-=sub_chunk_len;
289 } else {
290 DEBUGF("Error reading esds\n");
291 return false;
294 DEBUGF("entry_remaining=%ld\n",(long)entry_remaining);
295 stream_skip(qtmovie->stream,entry_remaining);
297 } else {
298 DEBUGF("expecting 'alac' or 'mp4a' data format, got %c%c%c%c\n",
299 SPLITFOURCC(qtmovie->res->format));
300 return false;
303 return true;
306 static bool read_chunk_stts(qtmovie_t *qtmovie, size_t chunk_len)
308 unsigned int i;
309 uint32_t numentries;
310 size_t size_remaining = chunk_len - 8;
312 /* version */
313 stream_read_uint8(qtmovie->stream);
314 size_remaining -= 1;
315 /* flags */
316 stream_read_uint8(qtmovie->stream);
317 stream_read_uint8(qtmovie->stream);
318 stream_read_uint8(qtmovie->stream);
319 size_remaining -= 3;
321 numentries = stream_read_uint32(qtmovie->stream);
322 size_remaining -= 4;
324 qtmovie->res->num_time_to_samples = numentries;
325 qtmovie->res->time_to_sample = malloc(numentries * sizeof(*qtmovie->res->time_to_sample));
327 if (!qtmovie->res->time_to_sample)
329 DEBUGF("stts too large\n");
330 return false;
333 for (i = 0; i < numentries; i++)
335 qtmovie->res->time_to_sample[i].sample_count = stream_read_uint32(qtmovie->stream);
336 qtmovie->res->time_to_sample[i].sample_duration = stream_read_uint32(qtmovie->stream);
337 size_remaining -= 8;
340 if (size_remaining)
342 DEBUGF("ehm, size remianing?\n");
343 stream_skip(qtmovie->stream, size_remaining);
346 return true;
349 static bool read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
351 unsigned int i;
352 uint32_t numentries;
353 size_t size_remaining = chunk_len - 8;
355 /* version */
356 stream_read_uint8(qtmovie->stream);
357 size_remaining -= 1;
358 /* flags */
359 stream_read_uint8(qtmovie->stream);
360 stream_read_uint8(qtmovie->stream);
361 stream_read_uint8(qtmovie->stream);
362 size_remaining -= 3;
364 /* default sample size */
365 if (stream_read_uint32(qtmovie->stream) != 0)
367 DEBUGF("i was expecting variable samples sizes\n");
368 stream_read_uint32(qtmovie->stream);
369 size_remaining -= 4;
370 return true;
372 size_remaining -= 4;
374 numentries = stream_read_uint32(qtmovie->stream);
375 size_remaining -= 4;
377 qtmovie->res->num_sample_byte_sizes = numentries;
378 qtmovie->res->sample_byte_size = malloc(numentries * sizeof(*qtmovie->res->sample_byte_size));
380 if (!qtmovie->res->sample_byte_size)
382 DEBUGF("stsz too large\n");
383 return false;
386 for (i = 0; i < numentries; i++)
388 uint32_t v = stream_read_uint32(qtmovie->stream);
390 if (v > 0x0000ffff)
392 DEBUGF("stsz[%d] > 65 kB (%ld)\n", i, (long)v);
393 return false;
396 qtmovie->res->sample_byte_size[i] = v;
397 size_remaining -= 4;
400 if (size_remaining)
402 DEBUGF("ehm, size remianing?\n");
403 stream_skip(qtmovie->stream, size_remaining);
406 return true;
409 static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len)
411 unsigned int i;
412 uint32_t numentries;
413 size_t size_remaining = chunk_len - 8;
415 /* version + flags */
416 stream_read_uint32(qtmovie->stream);
417 size_remaining -= 4;
419 numentries = stream_read_uint32(qtmovie->stream);
420 size_remaining -= 4;
422 qtmovie->res->num_sample_to_chunks = numentries;
423 qtmovie->res->sample_to_chunk = malloc(numentries *
424 sizeof(*qtmovie->res->sample_to_chunk));
426 if (!qtmovie->res->sample_to_chunk)
428 DEBUGF("stsc too large\n");
429 return false;
432 for (i = 0; i < numentries; i++)
434 qtmovie->res->sample_to_chunk[i].first_chunk =
435 stream_read_uint32(qtmovie->stream);
436 qtmovie->res->sample_to_chunk[i].num_samples =
437 stream_read_uint32(qtmovie->stream);
438 stream_read_uint32(qtmovie->stream);
439 size_remaining -= 12;
442 if (size_remaining)
444 DEBUGF("ehm, size remianing?\n");
445 stream_skip(qtmovie->stream, size_remaining);
448 return true;
451 static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len)
453 unsigned int i;
454 uint32_t numentries;
455 size_t size_remaining = chunk_len - 8;
457 /* version + flags */
458 stream_read_uint32(qtmovie->stream);
459 size_remaining -= 4;
461 numentries = stream_read_uint32(qtmovie->stream);
462 size_remaining -= 4;
464 qtmovie->res->num_chunk_offsets = numentries;
465 qtmovie->res->chunk_offset = malloc(numentries *
466 sizeof(*qtmovie->res->chunk_offset));
468 if (!qtmovie->res->chunk_offset)
470 DEBUGF("stco too large\n");
471 return false;
474 for (i = 0; i < numentries; i++)
476 qtmovie->res->chunk_offset[i] = stream_read_uint32(qtmovie->stream);
477 size_remaining -= 4;
480 if (size_remaining)
482 DEBUGF("ehm, size remianing?\n");
483 stream_skip(qtmovie->stream, size_remaining);
486 return true;
489 static bool read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
491 size_t size_remaining = chunk_len - 8;
493 while (size_remaining)
495 size_t sub_chunk_len;
496 fourcc_t sub_chunk_id;
498 sub_chunk_len = stream_read_uint32(qtmovie->stream);
499 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
501 DEBUGF("strange size (%lu) for chunk inside stbl\n",
502 (unsigned long)sub_chunk_len);
503 return false;
506 sub_chunk_id = stream_read_uint32(qtmovie->stream);
508 switch (sub_chunk_id)
510 case MAKEFOURCC('s','t','s','d'):
511 if (!read_chunk_stsd(qtmovie, sub_chunk_len)) {
512 return false;
514 break;
515 case MAKEFOURCC('s','t','t','s'):
516 if (!read_chunk_stts(qtmovie, sub_chunk_len))
518 return false;
520 break;
521 case MAKEFOURCC('s','t','s','z'):
522 if (!read_chunk_stsz(qtmovie, sub_chunk_len))
524 return false;
526 break;
527 case MAKEFOURCC('s','t','s','c'):
528 if (!read_chunk_stsc(qtmovie, sub_chunk_len))
530 return false;
532 break;
533 case MAKEFOURCC('s','t','c','o'):
534 if (!read_chunk_stco(qtmovie, sub_chunk_len))
536 return false;
538 break;
539 default:
540 /*DEBUGF("(stbl) unknown chunk id: %c%c%c%c\n",
541 SPLITFOURCC(sub_chunk_id));*/
542 stream_skip(qtmovie->stream, sub_chunk_len - 8);
545 size_remaining -= sub_chunk_len;
547 return true;
550 static bool read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
552 size_t size_remaining = chunk_len - 8;
553 uint32_t i;
555 /* Check for smhd, only kind of minf we care about */
557 if ((i = stream_read_uint32(qtmovie->stream)) != 16)
559 DEBUGF("unexpected size in media info: %ld\n", (long)i);
560 stream_skip(qtmovie->stream, size_remaining-4);
561 return true;
564 if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','m','h','d'))
566 DEBUGF("not a sound header! can't handle this.\n");
567 return false;
570 /* now skip the rest of the atom */
571 stream_skip(qtmovie->stream, 16 - 8);
572 size_remaining -= 16;
574 while (size_remaining)
576 size_t sub_chunk_len;
577 fourcc_t sub_chunk_id;
579 sub_chunk_len = stream_read_uint32(qtmovie->stream);
581 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
583 DEBUGF("strange size (%lu) for chunk inside minf\n",
584 (unsigned long)sub_chunk_len);
585 return false;
588 sub_chunk_id = stream_read_uint32(qtmovie->stream);
590 switch (sub_chunk_id)
592 case MAKEFOURCC('s','t','b','l'):
593 if (!read_chunk_stbl(qtmovie, sub_chunk_len)) {
594 return false;
596 break;
597 default:
598 /*DEBUGF("(minf) unknown chunk id: %c%c%c%c\n",
599 SPLITFOURCC(sub_chunk_id));*/
600 stream_skip(qtmovie->stream, sub_chunk_len - 8);
601 break;
604 size_remaining -= sub_chunk_len;
606 return true;
609 static bool read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
611 size_t size_remaining = chunk_len - 8;
613 while (size_remaining)
615 size_t sub_chunk_len;
616 fourcc_t sub_chunk_id;
618 sub_chunk_len = stream_read_uint32(qtmovie->stream);
619 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
621 DEBUGF("strange size (%lu) for chunk inside mdia\n",
622 (unsigned long)sub_chunk_len);
623 return false;
626 sub_chunk_id = stream_read_uint32(qtmovie->stream);
628 switch (sub_chunk_id)
630 case MAKEFOURCC('m','i','n','f'):
631 if (!read_chunk_minf(qtmovie, sub_chunk_len)) {
632 return false;
634 break;
635 default:
636 /*DEBUGF("(mdia) unknown chunk id: %c%c%c%c\n",
637 SPLITFOURCC(sub_chunk_id));*/
638 stream_skip(qtmovie->stream, sub_chunk_len - 8);
639 break;
642 size_remaining -= sub_chunk_len;
644 return true;
647 /* 'trak' - a movie track - contains other atoms */
648 static bool read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
650 size_t size_remaining = chunk_len - 8;
652 while (size_remaining)
654 size_t sub_chunk_len;
655 fourcc_t sub_chunk_id;
657 sub_chunk_len = stream_read_uint32(qtmovie->stream);
658 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
660 DEBUGF("strange size (%lu) for chunk inside trak\n",
661 (unsigned long)sub_chunk_len);
662 return false;
665 sub_chunk_id = stream_read_uint32(qtmovie->stream);
667 switch (sub_chunk_id)
669 case MAKEFOURCC('m','d','i','a'):
670 if (!read_chunk_mdia(qtmovie, sub_chunk_len)) {
671 return false;
673 break;
674 default:
675 /*DEBUGF("(trak) unknown chunk id: %c%c%c%c\n",
676 SPLITFOURCC(sub_chunk_id));*/
677 stream_skip(qtmovie->stream, sub_chunk_len - 8);
678 break;
681 size_remaining -= sub_chunk_len;
683 return true;
686 /* 'moov' movie atom - contains other atoms */
687 static bool read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
689 size_t size_remaining = chunk_len - 8;
691 while (size_remaining)
693 size_t sub_chunk_len;
694 fourcc_t sub_chunk_id;
696 sub_chunk_len = stream_read_uint32(qtmovie->stream);
697 if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
699 DEBUGF("strange size (%lu) for chunk inside moov\n",
700 (unsigned long)sub_chunk_len);
701 return false;
704 sub_chunk_id = stream_read_uint32(qtmovie->stream);
706 switch (sub_chunk_id)
708 case MAKEFOURCC('t','r','a','k'):
709 if (!read_chunk_trak(qtmovie, sub_chunk_len)) {
710 return false;
712 break;
713 default:
714 /*DEBUGF("(moov) unknown chunk id: %c%c%c%c\n",
715 SPLITFOURCC(sub_chunk_id));*/
716 stream_skip(qtmovie->stream, sub_chunk_len - 8);
717 break;
720 size_remaining -= sub_chunk_len;
722 return true;
725 static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len)
727 size_t size_remaining = chunk_len - 8;
729 qtmovie->res->mdat_len = size_remaining;
732 int qtmovie_read(stream_t *file, demux_res_t *demux_res)
734 qtmovie_t qtmovie;
736 /* construct the stream */
737 qtmovie.stream = file;
738 qtmovie.res = demux_res;
740 /* read the chunks */
741 while (1)
743 size_t chunk_len;
744 fourcc_t chunk_id;
746 chunk_len = stream_read_uint32(qtmovie.stream);
747 if (stream_eof(qtmovie.stream))
749 if(qtmovie.res->mdat_offset == 0 || qtmovie.res->format == 0)
750 return 0;
751 stream_seek(qtmovie.stream, qtmovie.res->mdat_offset);
752 return 1;
755 if (chunk_len == 1)
757 //DEBUGF("need 64bit support\n");
758 return 0;
760 chunk_id = stream_read_uint32(qtmovie.stream);
762 //DEBUGF("Found a chunk %c%c%c%c, length=%d\n",SPLITFOURCC(chunk_id),chunk_len);
763 switch (chunk_id)
765 case MAKEFOURCC('f','t','y','p'):
766 read_chunk_ftyp(&qtmovie, chunk_len);
767 break;
768 case MAKEFOURCC('m','o','o','v'):
769 if (!read_chunk_moov(&qtmovie, chunk_len)) {
770 return 0;
772 break;
773 case MAKEFOURCC('m','d','a','t'):
774 /* There can be empty mdats before the real one. If so, skip them */
775 if (chunk_len == 8)
776 break;
777 read_chunk_mdat(&qtmovie, chunk_len);
778 qtmovie.res->mdat_offset=stream_tell(qtmovie.stream);
779 /* If we've already seen the format, assume there's nothing
780 interesting after the mdat chunk (the file is "streamable").
781 This avoids having to seek, which might cause rebuffering. */
782 if(qtmovie.res->format > 0)
783 return 1;
784 stream_skip(qtmovie.stream, chunk_len - 8);
785 break;
787 /* these following atoms can be skipped !!!! */
788 case MAKEFOURCC('f','r','e','e'):
789 stream_skip(qtmovie.stream, chunk_len - 8);
790 break;
791 default:
792 //DEBUGF("(top) unknown chunk id: %c%c%c%c\n",SPLITFOURCC(chunk_id));
793 return 0;
797 return 0;