#include "mp4.h"
struct mp4_track {
- bool is_audio;
uint16_t channelCount;
uint16_t sampleRate;
/* stts */
uint32_t stts_entry_count;
uint32_t *stts_sample_count;
- uint32_t *stts_sample_delta;
/* stsc */
uint32_t stsc_entry_count;
uint32_t *stsc_first_chunk;
uint32_t *stsc_samples_per_chunk;
- uint32_t *stsc_sample_desc_index;
/* stsc */
uint32_t stco_entry_count;
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;
return ret;
t->stts_sample_count = para_malloc(t->stts_entry_count
* sizeof(int32_t));
- t->stts_sample_delta = para_malloc(t->stts_entry_count
- * sizeof (int32_t));
for (i = 0; i < t->stts_entry_count; i++) {
ret = read_int32(f, &t->stts_sample_count[i]);
if (ret <= 0)
return ret;
- ret = read_int32(f, &t->stts_sample_delta[i]);
+ ret = read_int32(f, NULL); /* sample delta */
if (ret <= 0)
return ret;
}
t->stsc_first_chunk = para_malloc(t->stsc_entry_count * sizeof(int32_t));
t->stsc_samples_per_chunk = para_malloc(t->stsc_entry_count
* sizeof (int32_t));
- t->stsc_sample_desc_index = para_malloc(t->stsc_entry_count *
- sizeof (int32_t));
-
for (i = 0; i < t->stsc_entry_count; i++) {
ret = read_int32(f, &t->stsc_first_chunk[i]);
if (ret <= 0)
ret = read_int32(f, &t->stsc_samples_per_chunk[i]);
if (ret <= 0)
return ret;
- ret = read_int32(f, &t->stsc_sample_desc_index[i]);
+ ret = read_int32(f, NULL); /* sample desc index */
if (ret <= 0)
return ret;
}
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;
} 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;
}
if (f->track[i]) {
free(f->track[i]->stsz_table);
free(f->track[i]->stts_sample_count);
- free(f->track[i]->stts_sample_delta);
free(f->track[i]->stsc_first_chunk);
free(f->track[i]->stsc_samples_per_chunk);
- free(f->track[i]->stsc_sample_desc_index);
free(f->track[i]->stco_chunk_offset);
free(f->track[i]);
}
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;
}
/**
- * 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 {
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;
}