From: Andre Noll Date: Wed, 11 Aug 2021 13:41:37 +0000 (+0200) Subject: mp4: Introduce mp4ff_get_duration(). X-Git-Tag: v0.7.1~7^2~105 X-Git-Url: http://git.tuebingen.mpg.de/?a=commitdiff_plain;ds=sidebyside;h=15aeb1f5cc5bf5c4925897d5ae54d2b350822790;p=paraslash.git mp4: Introduce mp4ff_get_duration(). This allows us to get rid of an ugly hack in aac_afh.c where we peeked at the audio-specific config structure to get the scaling factor which was needed to compute the duration. --- diff --git a/aac_afh.c b/aac_afh.c index dd9247d7..15e338e5 100644 --- a/aac_afh.c +++ b/aac_afh.c @@ -24,7 +24,6 @@ struct aac_afh_context { size_t fpos; int32_t track; struct mp4ff *mp4ff; - mp4AudioSpecificConfig masc; struct mp4ff_callback cb; }; @@ -50,7 +49,7 @@ static uint32_t aac_afh_seek_cb(void *user_data, uint64_t pos) return 0; } -static int32_t aac_afh_get_track(struct mp4ff *mp4ff, mp4AudioSpecificConfig *masc) +static int32_t aac_afh_get_track(struct mp4ff *mp4ff) { int32_t i, rc, num_tracks = mp4ff_total_tracks(mp4ff); @@ -61,7 +60,8 @@ static int32_t aac_afh_get_track(struct mp4ff *mp4ff, mp4AudioSpecificConfig *ma mp4ff_get_decoder_config(mp4ff, i, &buf, &buf_size); if (buf) { - rc = NeAACDecAudioSpecificConfig(buf, buf_size, masc); + mp4AudioSpecificConfig masc; + rc = NeAACDecAudioSpecificConfig(buf, buf_size, &masc); free(buf); if (rc < 0) continue; @@ -87,7 +87,7 @@ static int aac_afh_open(const void *map, size_t mapsize, void **afh_context) c->mp4ff = mp4ff_open_read(&c->cb); if (!c->mp4ff) goto free_ctx; - c->track = aac_afh_get_track(c->mp4ff, &c->masc); + c->track = aac_afh_get_track(c->mp4ff); ret = -E_MP4FF_TRACK; if (c->track < 0) goto close_mp4ff; @@ -145,7 +145,7 @@ static int aac_get_file_info(char *map, size_t numbytes, __a_unused int fd, int ret; int32_t rv; struct aac_afh_context *c; - int64_t tmp; + uint64_t milliseconds; const char *buf; uint32_t n, len; @@ -176,11 +176,9 @@ 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); } - - tmp = c->masc.sbr_present_flag == 1? 2048 : 1024; - afhi->seconds_total = tmp * afhi->chunks_total / afhi->frequency; - ms2tv(1000 * tmp / afhi->frequency, &afhi->chunk_tv); - + milliseconds = mp4ff_get_duration(c->mp4ff, c->track); + afhi->seconds_total = milliseconds / 1000; + ms2tv(milliseconds / afhi->chunks_total, &afhi->chunk_tv); if (aac_afh_get_chunk(0, c, &buf, &len) >= 0) numbytes -= buf - map; afhi->bitrate = 8 * numbytes / afhi->seconds_total / 1000; diff --git a/mp4.c b/mp4.c index 548f78ec..46aec2db 100644 --- a/mp4.c +++ b/mp4.c @@ -765,7 +765,6 @@ static int32_t tag_add_field(struct mp4ff_metadata *tags, const char *item, { if (!item || (item && !*item) || !value) return 0; - tags->tags = para_realloc(tags->tags, (tags->count + 1) * sizeof(struct mp4ff_tag)); tags->tags[tags->count].item = para_strdup(item); @@ -1408,6 +1407,24 @@ static int32_t sample_to_offset(const struct mp4ff *f, int32_t track, return chunk_offset2; } +/** + * Return the number of milliseconds of the given track. + * + * \param f As returned by \ref mp4ff_open_read(), must not be NULL. + * \param track Between zero and the value returned by \ref mp4ff_total_tracks(). + * + * The function returns zero if the audio file is of zero length or contains a + * corrupt track header. + */ +uint64_t mp4ff_get_duration(const struct mp4ff *f, int32_t track) +{ + const struct mp4ff_track *t = f->track[track]; + + if (t->timeScale == 0) + return 0; + return t->duration * 1000 / t->timeScale; +} + void mp4ff_set_sample_position(struct mp4ff *f, int32_t track, int32_t sample) { int32_t offset = sample_to_offset(f, track, sample); diff --git a/mp4.h b/mp4.h index 8cd08ccf..ecab89b3 100644 --- a/mp4.h +++ b/mp4.h @@ -30,6 +30,7 @@ int32_t mp4ff_get_sample_size(const struct mp4ff *f, int track, int sample); uint32_t mp4ff_get_sample_rate(const struct mp4ff *f, int32_t track); uint32_t mp4ff_get_channel_count(const struct mp4ff * f, int32_t track); int32_t mp4ff_num_samples(const struct mp4ff *f, int track); +uint64_t mp4ff_get_duration(const struct mp4ff *f, int32_t track); struct mp4ff *mp4ff_open_read_metaonly(struct mp4ff_callback *f); int mp4ff_meta_get_by_index(const struct mp4ff *f, unsigned int index,