]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - mp4.c
mp4: Merge sample_to_offset() into mp4_set_sample_position().
[paraslash.git] / mp4.c
diff --git a/mp4.c b/mp4.c
index 3e7a74a88d4c3c2c401fc77947c77296045c8d1f..1b387534d6adcbca4521472d473ebad49c7973cb 100644 (file)
--- 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;
 }