From: Andre Noll Date: Thu, 19 Aug 2021 13:52:13 +0000 (+0200) Subject: mp4: Hide tracks array. X-Git-Tag: v0.7.1~7^2~49 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=7376b51bb47f834f46a06756d3f004efac6c9bb0;p=paraslash.git mp4: Hide tracks array. All functions of mp4.c operate on the first audio track. This patch makes this fact implicit which allows us to remove the public mp4_get_total_tracks() and mp4_is_audio_track(). Moreover, the track parameter can be removed from all public functions. If no audio track was found in the mp4 file, we now return an error from two public open functions of mp4.c. Otherwise, we maintain a pointer to the first audio track within the mp4 structure and use that to identify the track rather than letting the API users pass the track number. --- diff --git a/aac_afh.c b/aac_afh.c index f41b3c2b..42cba27a 100644 --- a/aac_afh.c +++ b/aac_afh.c @@ -22,7 +22,6 @@ struct aac_afh_context { const void *map; size_t mapsize; size_t fpos; - int32_t track; struct mp4 *mp4; struct mp4_callback cb; }; @@ -49,17 +48,6 @@ static uint32_t aac_afh_seek_cb(void *user_data, uint64_t pos) return 0; } -static int32_t aac_afh_get_track(struct mp4 *mp4) -{ - int32_t i, num_tracks = mp4_get_total_tracks(mp4); - - assert(num_tracks >= 0); - for (i = 0; i < num_tracks; i++) - if (mp4_is_audio_track(mp4, i)) - return i; - return -E_MP4_TRACK; /* no audio track */ -} - static int aac_afh_open(const void *map, size_t mapsize, void **afh_context) { int ret; @@ -76,14 +64,8 @@ static int aac_afh_open(const void *map, size_t mapsize, void **afh_context) c->mp4 = mp4_open_read(&c->cb); if (!c->mp4) goto free_ctx; - ret = aac_afh_get_track(c->mp4); - if (ret < 0) - goto close_mp4; - c->track = ret; *afh_context = c; return 0; -close_mp4: - mp4_close(c->mp4); free_ctx: free(c); *afh_context = NULL; @@ -105,11 +87,11 @@ static int aac_afh_get_chunk(uint32_t chunk_num, void *afh_context, size_t offset; int ret; - ret = mp4_set_sample_position(c->mp4, c->track, chunk_num); + ret = mp4_set_sample_position(c->mp4, chunk_num); if (ret < 0) return ret; offset = c->fpos; - ss = mp4_get_sample_size(c->mp4, c->track, chunk_num); + ss = mp4_get_sample_size(c->mp4, chunk_num); if (ss <= 0) return -E_MP4_BAD_SAMPLE; assert(ss + offset <= c->mapsize); @@ -145,19 +127,19 @@ static int aac_get_file_info(char *map, size_t numbytes, __a_unused int fd, return ret; ret = -E_MP4_BAD_SAMPLERATE; - rv = mp4_get_sample_rate(c->mp4, c->track); + rv = mp4_get_sample_rate(c->mp4); if (rv <= 0) goto close; afhi->frequency = rv; ret = -E_MP4_BAD_CHANNEL_COUNT; - rv = mp4_get_channel_count(c->mp4, c->track); + rv = mp4_get_channel_count(c->mp4); if (rv <= 0) goto close; afhi->channels = rv; ret = -E_MP4_BAD_SAMPLE_COUNT; - rv = mp4_num_samples(c->mp4, c->track); + rv = mp4_num_samples(c->mp4); if (rv <= 0) goto close; afhi->chunks_total = rv; @@ -167,7 +149,7 @@ static int aac_get_file_info(char *map, size_t numbytes, __a_unused int fd, break; afhi->max_chunk_size = PARA_MAX(afhi->max_chunk_size, len); } - milliseconds = mp4_get_duration(c->mp4, c->track); + milliseconds = mp4_get_duration(c->mp4); afhi->seconds_total = milliseconds / 1000; ms2tv(milliseconds / afhi->chunks_total, &afhi->chunk_tv); if (aac_afh_get_chunk(0, c, &buf, &len) >= 0) diff --git a/mp4.c b/mp4.c index 71858305..09a3c743 100644 --- a/mp4.c +++ b/mp4.c @@ -14,7 +14,6 @@ #include "mp4.h" struct mp4_track { - bool is_audio; uint16_t channelCount; uint16_t sampleRate; @@ -57,6 +56,8 @@ struct mp4 { int32_t total_tracks; /* track data */ struct mp4_track *track[MAX_TRACKS]; + /* the first audio track found */ + struct mp4_track *audio_track; /* metadata */ struct mp4_metadata meta; @@ -647,9 +648,10 @@ static int read_stsd(struct mp4 *f) if (ret <= 0) return ret; skip += size; - t->is_audio = atom_type == ATOM_MP4A; - if (t->is_audio) + if (!f->audio_track && atom_type == ATOM_MP4A) { + f->audio_track = t; read_mp4a(f); + } set_position(f, skip); } return 1; @@ -933,12 +935,16 @@ static int parse_atoms(struct mp4 *f, int meta_only) } else if (atom_type < SUBATOMIC) { ret = parse_sub_atoms(f, size - header_size, meta_only); if (ret <= 0) - return ret; + break; } else { /* skip this atom */ set_position(f, get_position(f) + size - header_size); } } + if (ret < 0) + return ret; + if (!f->audio_track) + return -E_MP4_TRACK; return ret; } @@ -980,10 +986,10 @@ void mp4_close(struct mp4 *f) free(f); } -static int32_t chunk_of_sample(const struct mp4 *f, int32_t track, - int32_t sample, int32_t *chunk) +static int32_t chunk_of_sample(const struct mp4 *f, int32_t sample, + int32_t *chunk) { - const struct mp4_track *t = f->track[track]; + const struct mp4_track *t = f->audio_track; uint32_t *fc = t->stsc_first_chunk, *spc = t->stsc_samples_per_chunk; int32_t chunk1, chunk1samples, n, total, i; @@ -1002,51 +1008,28 @@ static int32_t chunk_of_sample(const struct mp4 *f, int32_t track, } /** - * Return the number of milliseconds of the given track. + * Return the number of milliseconds of the audio 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_get_total_tracks(). - * - * The function returns zero if the audio file is of zero length or contains a - * corrupt track header. */ -uint64_t mp4_get_duration(const struct mp4 *f, int32_t track) +uint64_t mp4_get_duration(const struct mp4 *f) { - const struct mp4_track *t = f->track[track]; + const struct mp4_track *t = f->audio_track; if (t->timeScale == 0) return 0; return t->duration * 1000 / t->timeScale; } -int32_t mp4_get_total_tracks(const struct mp4 *f) +int mp4_set_sample_position(struct mp4 *f, int32_t sample) { - return f->total_tracks; -} - -/** - * Check whether the given track number corresponds to an audio track. - * - * \param f See \ref mp4_get_duration(). - * \param track See \ref mp4_get_duration(). - * - * Besides audio tracks, an mp4 file may contain video and system tracks. For - * those the function returns false. - */ -bool mp4_is_audio_track(const struct mp4 *f, int32_t track) -{ - return f->track[track]->is_audio; -} - -int mp4_set_sample_position(struct mp4 *f, uint32_t track, int32_t sample) -{ - const struct mp4_track *t = f->track[track]; + const struct mp4_track *t = f->audio_track; int32_t offset, chunk, chunk_sample; uint32_t n, srs; /* sample range size */ - if (sample >= t->stsz_sample_count || track >= f->total_tracks) + if (sample >= t->stsz_sample_count) return -ERRNO_TO_PARA_ERROR(EINVAL); - chunk_sample = chunk_of_sample(f, track, sample, &chunk); + chunk_sample = chunk_of_sample(f, sample, &chunk); if (t->stsz_sample_size > 0) srs = (sample - chunk_sample) * t->stsz_sample_size; else { @@ -1063,33 +1046,33 @@ int mp4_set_sample_position(struct mp4 *f, uint32_t track, int32_t sample) return 1; } -int32_t mp4_get_sample_size(const struct mp4 *f, int track, int sample) +int32_t mp4_get_sample_size(const struct mp4 *f, int sample) { - const struct mp4_track *t = f->track[track]; + const struct mp4_track *t = f->audio_track; if (t->stsz_sample_size != 0) return t->stsz_sample_size; return t->stsz_table[sample]; } -uint32_t mp4_get_sample_rate(const struct mp4 *f, int32_t track) +uint32_t mp4_get_sample_rate(const struct mp4 *f) { - return f->track[track]->sampleRate; + return f->audio_track->sampleRate; } -uint32_t mp4_get_channel_count(const struct mp4 *f, int32_t track) +uint32_t mp4_get_channel_count(const struct mp4 *f) { - return f->track[track]->channelCount; + return f->audio_track->channelCount ; } -int32_t mp4_num_samples(const struct mp4 *f, int32_t track) +int32_t mp4_num_samples(const struct mp4 *f) { + const struct mp4_track *t = f->audio_track; int32_t i; int32_t total = 0; - for (i = 0; i < f->track[track]->stts_entry_count; i++) { - total += f->track[track]->stts_sample_count[i]; - } + for (i = 0; i < t->stts_entry_count; i++) + total += t->stts_sample_count[i]; return total; } diff --git a/mp4.h b/mp4.h index e7ca0d96..1142925d 100644 --- a/mp4.h +++ b/mp4.h @@ -19,16 +19,14 @@ struct mp4_metadata { struct mp4; /* opaque */ -int mp4_set_sample_position(struct mp4 *f, uint32_t track, int32_t sample); -int32_t mp4_get_total_tracks(const struct mp4 *f); -bool mp4_is_audio_track(const struct mp4 *f, int32_t track); +int mp4_set_sample_position(struct mp4 *f, int32_t sample); struct mp4 *mp4_open_read(const struct mp4_callback *cb); void mp4_close(struct mp4 *f); -int32_t mp4_get_sample_size(const struct mp4 *f, int track, int sample); -uint32_t mp4_get_sample_rate(const struct mp4 *f, int32_t track); -uint32_t mp4_get_channel_count(const struct mp4 * f, int32_t track); -int32_t mp4_num_samples(const struct mp4 *f, int track); -uint64_t mp4_get_duration(const struct mp4 *f, int32_t track); +int32_t mp4_get_sample_size(const struct mp4 *f, int sample); +uint32_t mp4_get_sample_rate(const struct mp4 *f); +uint32_t mp4_get_channel_count(const struct mp4 * f); +int32_t mp4_num_samples(const struct mp4 *f); +uint64_t mp4_get_duration(const struct mp4 *f); struct mp4 *mp4_open_meta(const struct mp4_callback *cb); struct mp4_metadata *mp4_get_meta(struct mp4 *f);