--- apps/codecs/libm4a/demux.c 2006-02-12 20:07:28.000000000 -0500 +++ apps/codecs/libm4a/demux.c 2006-02-12 20:10:26.000000000 -0500 @@ -47,6 +47,7 @@ { stream_t *stream; demux_res_t *res; + long saved_mdat_pos; } qtmovie_t; @@ -93,6 +94,22 @@ stream_skip(qtmovie->stream, size_remaining); } +static void read_chunk_edts(qtmovie_t *qtmovie, size_t chunk_len) +{ + /* don't need anything from here atm, skip */ + size_t size_remaining = chunk_len - 8; /* FIXME WRONG */ + + stream_skip(qtmovie->stream, size_remaining); +} + +static void read_chunk_elst(qtmovie_t *qtmovie, size_t chunk_len) +{ + /* don't need anything from here atm, skip */ + size_t size_remaining = chunk_len - 8; /* FIXME WRONG */ + + stream_skip(qtmovie->stream, size_remaining); +} + /* media handler inside mdia */ static void read_chunk_hdlr(qtmovie_t *qtmovie, size_t chunk_len) { @@ -193,7 +210,7 @@ if (temp < 13) return false; audioType = stream_read_uint8(qtmovie->stream); - temp=stream_read_int32(qtmovie->stream);//0x15000414 ???? + temp=stream_read_int32(qtmovie->stream); /* 0x15000414 ???? */ maxBitrate = stream_read_int32(qtmovie->stream); avgBitrate = stream_read_int32(qtmovie->stream); @@ -263,8 +280,8 @@ entry_remaining -= 6; version = stream_read_uint16(qtmovie->stream); - // if (version != 1) - //fprintf(stderr, "unknown version??\n"); + /* if (version != 1) + DEBUGF("unknown version??\n"); */ entry_remaining -= 2; /* revision level */ @@ -459,7 +476,8 @@ sub_chunk_len = stream_read_uint32(qtmovie->stream); if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining) { - DEBUGF("strange size for chunk inside stbl\n"); + DEBUGF("strange size for chunk inside stbl (%i) (remaining: %i)\n", + sub_chunk_len, size_remaining); return false; } @@ -623,6 +641,9 @@ return false; } break; + case MAKEFOURCC('e','d','t','s'): + read_chunk_edts(qtmovie, sub_chunk_len); + break; default: DEBUGF("(trak) unknown chunk id: %c%c%c%c\n", SPLITFOURCC(sub_chunk_id)); @@ -685,6 +706,9 @@ case MAKEFOURCC('u','d','t','a'): read_chunk_udta(qtmovie, sub_chunk_len); break; + case MAKEFOURCC('e','l','s','t'): + read_chunk_elst(qtmovie, sub_chunk_len); + break; default: DEBUGF("(moov) unknown chunk id: %c%c%c%c\n", SPLITFOURCC(sub_chunk_id)); @@ -696,11 +720,16 @@ return true; } -static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len) +static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len, int skip_mdat) { size_t size_remaining = chunk_len - 8; /* FIXME WRONG */ qtmovie->res->mdat_len = size_remaining; + if (skip_mdat) + { + qtmovie->saved_mdat_pos = stream_tell(qtmovie->stream); + stream_skip(qtmovie->stream, size_remaining); + } #if 0 qtmovie->res->mdat = malloc(size_remaining); @@ -708,14 +737,35 @@ #endif } +static int set_saved_mdat(qtmovie_t *qtmovie) +{ + if (qtmovie->saved_mdat_pos == -1) + { + DEBUGF("stream contains mdat before moov but is not seekable\n"); + return 0; + } + + /*if (stream_setpos(qtmovie->stream, qtmovie->saved_mdat_pos)) + { + DEBUGF("error while seeking stream to mdat pos\n"); + return 0; + }*/ + + return 1; +} + int qtmovie_read(stream_t *file, demux_res_t *demux_res) { + int found_moov = 0; + int found_mdat = 0; qtmovie_t qtmovie; /* construct the stream */ qtmovie.stream = file; qtmovie.res = demux_res; + memset(demux_res, 0, sizeof(demux_res_t)); + /* read the chunks */ while (1) { @@ -730,40 +780,44 @@ if (chunk_len == 1) { - //DEBUGF("need 64bit support\n"); + /* DEBUGF("need 64bit support\n"); */ return 0; } chunk_id = stream_read_uint32(qtmovie.stream); - //DEBUGF("Found a chunk %c%c%c%c, length=%d\n",SPLITFOURCC(chunk_id),chunk_len); + /* DEBUGF("Found a chunk %c%c%c%c, length=%d\n",SPLITFOURCC(chunk_id),chunk_len); */ switch (chunk_id) { case MAKEFOURCC('f','t','y','p'): read_chunk_ftyp(&qtmovie, chunk_len); break; case MAKEFOURCC('m','o','o','v'): - if (!read_chunk_moov(&qtmovie, chunk_len)) { - return 0; + read_chunk_moov(&qtmovie, chunk_len); + if (found_mdat) + { + return set_saved_mdat(&qtmovie); } + found_moov = 1; break; - /* once we hit mdat we stop reading and return. - * this is on the assumption that there is no furhter interesting - * stuff in the stream. if there is stuff will fail (:()). - * But we need the read pointer to be at the mdat stuff - * for the decoder. And we don't want to rely on fseek/ftell, - * as they may not always be avilable */ + /* if we hit mdat before we've found moov, record the position + * and move on. We can then come back to mdat later. + * This presumes the stream supports seeking backwards. + */ case MAKEFOURCC('m','d','a','t'): - read_chunk_mdat(&qtmovie, chunk_len); + read_chunk_mdat(&qtmovie, chunk_len, !found_moov); /* Keep track of start of stream in file - used for seeking */ qtmovie.res->mdat_offset=stream_tell(qtmovie.stream); - return 1; + if (found_moov) + return 1; + found_mdat = 1; + break; /* these following atoms can be skipped !!!! */ case MAKEFOURCC('f','r','e','e'): stream_skip(qtmovie.stream, chunk_len - 8); /* FIXME not 8 */ break; default: - //DEBUGF("(top) unknown chunk id: %c%c%c%c\n",SPLITFOURCC(chunk_id)); + /* DEBUGF("(top) unknown chunk id: %c%c%c%c\n",SPLITFOURCC(chunk_id)); */ return 0; }