X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=mp4.c;h=1b387534d6adcbca4521472d473ebad49c7973cb;hb=b3ac1dc38bb8366ece6cbaf2adf95e964e0295c7;hp=3e7a74a88d4c3c2c401fc77947c77296045c8d1f;hpb=5f123ac45aed8c3480e8211b513cf9b6bd7eb2ab;p=paraslash.git diff --git a/mp4.c b/mp4.c index 3e7a74a8..1b387534 100644 --- a/mp4.c +++ b/mp4.c @@ -52,11 +52,8 @@ struct mp4 { uint8_t last_atom; uint64_t file_size; - uint32_t error; - /* incremental track index while reading the file */ int32_t total_tracks; - /* track data */ struct mp4_track *track[MAX_TRACKS]; @@ -64,11 +61,6 @@ struct mp4 { struct mp4_metadata meta; }; -int32_t mp4_total_tracks(const struct mp4 *f) -{ - return f->total_tracks; -} - /* * Returns -1, 0, or 1 on errors/EOF/success. Partial reads followed by EOF or * read errors are treated as errors. @@ -180,16 +172,16 @@ enum atoms { ATOM_MVHD = 131, ATOM_TKHD = 132, ATOM_TREF = 133, - ATOM_MDHD = 134, + ATOM_MDHD = 134, /* track header */ ATOM_VMHD = 135, ATOM_SMHD = 136, ATOM_HMHD = 137, - ATOM_STSD = 138, - ATOM_STTS = 139, - ATOM_STSZ = 140, + ATOM_STSD = 138, /* sample description box */ + ATOM_STTS = 139, /* time to sample box */ + ATOM_STSZ = 140, /* sample size box */ ATOM_STZ2 = 141, - ATOM_STCO = 142, - ATOM_STSC = 143, + ATOM_STCO = 142, /* chunk offset box */ + ATOM_STSC = 143, /* sample to chunk box */ ATOM_MP4A = 144, ATOM_MP4V = 145, ATOM_MP4S = 146, @@ -445,18 +437,6 @@ static int32_t set_position(struct mp4 *f, int64_t position) return 0; } -static void track_add(struct mp4 *f) -{ - f->total_tracks++; - - if (f->total_tracks > MAX_TRACKS) { - f->total_tracks = 0; - f->error++; - return; - } - f->track[f->total_tracks - 1] = para_calloc(sizeof(struct mp4_track)); -} - static int read_stsz(struct mp4 *f) { int ret; @@ -870,34 +850,22 @@ static int32_t read_meta(struct mp4 *f, uint64_t size) return 1; } -static int32_t atom_read(struct mp4 *f, int32_t size, uint8_t atom_type) +static int atom_read(struct mp4 *f, uint64_t size, uint8_t atom_type) { uint64_t dest_position = get_position(f) + size - 8; - if (atom_type == ATOM_STSZ) { - /* sample size box */ - read_stsz(f); - } else if (atom_type == ATOM_STTS) { - /* time to sample box */ - read_stts(f); - } else if (atom_type == ATOM_STSC) { - /* sample to chunk box */ - read_stsc(f); - } else if (atom_type == ATOM_STCO) { - /* chunk offset box */ - read_stco(f); - } else if (atom_type == ATOM_STSD) { - /* sample description box */ - read_stsd(f); - } else if (atom_type == ATOM_MDHD) { - /* track header */ - read_mdhd(f); - } else if (atom_type == ATOM_META) { - /* iTunes Metadata box */ - read_meta(f, size); - } + int ret = 1; /* return success for atoms we don't care about */ + switch (atom_type) { + case ATOM_STSZ: ret = read_stsz(f); break; + case ATOM_STTS: ret = read_stts(f); break; + case ATOM_STSC: ret = read_stsc(f); break; + case ATOM_STCO: ret = read_stco(f); break; + case ATOM_STSD: ret = read_stsd(f); break; + case ATOM_MDHD: ret = read_mdhd(f); break; + case ATOM_META: ret = read_meta(f, size); break; + } set_position(f, dest_position); - return 0; + return ret; } /* parse atoms that are sub atoms of other atoms */ @@ -916,25 +884,31 @@ static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, int meta_only) if (size == 0) return -1; counted_size += size; - /* we're starting to read a new track, update index, - * so that all data and tables get written in the right place - */ - if (atom_type == ATOM_TRAK) - track_add(f); + if (atom_type == ATOM_TRAK) { + if (f->total_tracks >= MAX_TRACKS) + return -1; + f->total_tracks++; + f->track[f->total_tracks - 1] = para_calloc( + sizeof(struct mp4_track)); + } /* parse subatoms */ if (meta_only && !need_parse_when_meta_only(atom_type)) { set_position(f, get_position(f) + size - header_size); } else if (atom_type < SUBATOMIC) { - parse_sub_atoms(f, size - header_size, meta_only); + ret = parse_sub_atoms(f, size - header_size, meta_only); + if (ret <= 0) + return ret; } else { - atom_read(f, (uint32_t) size, atom_type); + ret = atom_read(f, size, atom_type); + if (ret <= 0) + return ret; } } return 1; } /* parse root atoms */ -static int32_t parse_atoms(struct mp4 *f, int meta_only) +static int parse_atoms(struct mp4 *f, int meta_only) { int ret; uint64_t size; @@ -956,7 +930,9 @@ static int32_t parse_atoms(struct mp4 *f, int meta_only) if (meta_only && !need_parse_when_meta_only(atom_type)) { set_position(f, get_position(f) + size - header_size); } else if (atom_type < SUBATOMIC) { - parse_sub_atoms(f, size - header_size, meta_only); + ret = parse_sub_atoms(f, size - header_size, meta_only); + if (ret <= 0) + return ret; } else { /* skip this atom */ set_position(f, get_position(f) + size - header_size); @@ -967,13 +943,14 @@ static int32_t parse_atoms(struct mp4 *f, int meta_only) struct mp4 *mp4_open_read(const struct mp4_callback *cb) { + int ret; struct mp4 *f = para_calloc(sizeof(struct mp4)); f->cb = cb; - parse_atoms(f, 0); - if (f->error) { + ret = parse_atoms(f, 0); + if (ret < 0) { free(f); - f = NULL; + return NULL; } return f; } @@ -1085,24 +1062,11 @@ static int32_t sample_range_size(const struct mp4 *f, int32_t track, return total; } -static int32_t sample_to_offset(const struct mp4 *f, int32_t track, - int32_t sample) -{ - int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2; - - chunk_of_sample(f, track, sample, &chunk_sample, &chunk); - - chunk_offset1 = chunk_to_offset(f, track, chunk); - chunk_offset2 = chunk_offset1 + sample_range_size(f, - track, chunk_sample, sample); - return chunk_offset2; -} - /** * Return the number of milliseconds of the given track. * * \param f As returned by \ref mp4_open_read(), must not be NULL. - * \param track Between zero and the value returned by \ref mp4_total_tracks(). + * \param track Between zero and the value returned by \ref mp4_get_total_tracks(). * * The function returns zero if the audio file is of zero length or contains a * corrupt track header. @@ -1116,6 +1080,11 @@ uint64_t mp4_get_duration(const struct mp4 *f, int32_t track) return t->duration * 1000 / t->timeScale; } +int32_t mp4_get_total_tracks(const struct mp4 *f) +{ + return f->total_tracks; +} + /** * Check whether the given track number corresponds to an audio track. * @@ -1132,7 +1101,11 @@ bool mp4_is_audio_track(const struct mp4 *f, int32_t track) void mp4_set_sample_position(struct mp4 *f, int32_t track, int32_t sample) { - int32_t offset = sample_to_offset(f, track, sample); + int32_t offset, chunk, chunk_sample; + + chunk_of_sample(f, track, sample, &chunk_sample, &chunk); + offset = chunk_to_offset(f, track, chunk) + + sample_range_size(f, track, chunk_sample, sample); set_position(f, offset); } @@ -1168,13 +1141,14 @@ int32_t mp4_num_samples(const struct mp4 *f, int32_t track) struct mp4 *mp4_open_meta(const struct mp4_callback *cb) { + int ret; struct mp4 *f = para_calloc(sizeof(struct mp4)); f->cb = cb; - parse_atoms(f, 1); - if (f->error) { + ret = parse_atoms(f, 1); + if (ret < 0) { free(f); - f = NULL; + return NULL; } return f; }