struct mp4 {
const struct mp4_callback *cb;
- int64_t current_position;
uint64_t moov_offset;
uint64_t moov_size;
uint32_t udta_size;
uint8_t last_atom;
- uint64_t file_size;
-
/* incremental track index while reading the file */
int32_t total_tracks;
/* track data */
/* regard EAGAIN as an error as reads should be blocking. */
if (ret <= 0)
return ret < 0? -1 : 0;
- f->current_position += ret;
size -= ret;
}
return 1;
uint8_t data[8];
int ret = read_data(f, data, 8);
- if (ret > 0 && result)
+ if (ret > 0)
*result = read_u64_be(data);
return ret;
}
uint8_t data[4];
int ret = read_data(f, data, 4);
- if (ret > 0 && result)
+ if (ret > 0)
*result = read_u32_be(data);
return ret;
}
-static int read_int24(struct mp4 *f, uint32_t *result)
-{
- uint8_t data[3];
- int ret = read_data(f, data, 3);
-
- if (ret > 0 && result)
- *result = read_u24_be(data);
- return ret;
-}
-
static int read_int16(struct mp4 *f, uint16_t *result)
{
uint8_t data[2];
int ret = read_data(f, data, 2);
- if (ret > 0 && result)
+ if (ret > 0)
*result = read_u16_be(data);
return ret;
}
-static uint8_t read_int8(struct mp4 *f, uint8_t *result)
-{
- uint8_t data[1];
- int ret = read_data(f, data, 1);
-
- if (ret > 0 && result)
- *result = data[0];
- return ret;
-}
-
#define ATOM_ITEMS \
ATOM_ITEM(MOOV, 'm', 'o', 'o', 'v') \
ATOM_ITEM(TRAK, 't', 'r', 'a', 'k') \
return 1;
}
-static int64_t get_position(const struct mp4 *f)
+static off_t get_position(const struct mp4 *f)
{
- return f->current_position;
+ return f->cb->seek(f->cb->user_data, 0, SEEK_CUR);
}
-static int32_t set_position(struct mp4 *f, int64_t position)
+static void set_position(struct mp4 *f, off_t position)
{
- f->cb->seek(f->cb->user_data, position);
- f->current_position = position;
+ f->cb->seek(f->cb->user_data, position, SEEK_SET);
+}
- return 0;
+static void skip_bytes(struct mp4 *f, off_t num_skip)
+{
+ f->cb->seek(f->cb->user_data, num_skip, SEEK_CUR);
}
static int read_stsz(struct mp4 *f)
if (f->total_tracks == 0)
return -1;
t = f->track[f->total_tracks - 1];
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
ret = read_int32(f, &t->stsz_sample_size);
if (ret <= 0)
return ret;
t = f->track[f->total_tracks - 1];
if (t->stts_entry_count)
return 0;
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
ret = read_int32(f, &t->stts_entry_count);
if (ret <= 0)
return ret;
ret = read_int32(f, &t->stts_sample_count[i]);
if (ret <= 0)
return ret;
- ret = read_int32(f, NULL); /* sample delta */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* sample delta */
}
return 1;
}
return -1;
t = f->track[f->total_tracks - 1];
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
ret = read_int32(f, &t->stsc_entry_count);
if (ret <= 0)
return ret;
ret = read_int32(f, &t->stsc_samples_per_chunk[i]);
if (ret <= 0)
return ret;
- ret = read_int32(f, NULL); /* sample desc index */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* sample desc index */
}
return 1;
}
return -1;
t = f->track[f->total_tracks - 1];
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
ret = read_int32(f, &t->stco_entry_count);
if (ret <= 0)
return ret;
return 1;
}
-static int read_mp4a(struct mp4 *f)
-{
- int ret;
- int32_t i;
- struct mp4_track *t;
-
- if (f->total_tracks == 0)
- return -1;
- t = f->track[f->total_tracks - 1];
-
- for (i = 0; i < 6; i++) {
- ret = read_int8(f, NULL); /* reserved */
- if (ret <= 0)
- return ret;
- }
- ret = read_int16(f, NULL); /* data_reference_index */
- if (ret <= 0)
- return ret;
- ret = read_int32(f, NULL); /* reserved */
- if (ret <= 0)
- return ret;
- ret = read_int32(f, NULL); /* reserved */
- if (ret <= 0)
- return ret;
- ret = read_int16(f, &t->channel_count);
- if (ret <= 0)
- return ret;
- ret = read_int16(f, NULL);
- if (ret <= 0)
- return ret;
- ret = read_int16(f, NULL);
- if (ret <= 0)
- return ret;
- ret = read_int16(f, NULL);
- if (ret <= 0)
- return ret;
- return read_int16(f, &t->sample_rate);
-}
-
static int read_stsd(struct mp4 *f)
{
int ret;
if (f->total_tracks == 0)
return -1;
t = f->track[f->total_tracks - 1];
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
ret = read_int32(f, &entry_count);
if (ret <= 0)
return ret;
skip += size;
if (!f->audio_track && atom_type == ATOM_MP4A) {
f->audio_track = t;
- read_mp4a(f);
+ /* reserved (6), data reference index (2), reserved (8) */
+ skip_bytes(f, 16);
+ ret = read_int16(f, &t->channel_count);
+ if (ret <= 0)
+ return ret;
+ skip_bytes(f, 6);
+ ret = read_int16(f, &t->sample_rate);
+ if (ret <= 0)
+ return ret;
}
set_position(f, skip);
}
destpos = get_position(f) + subsize - header_size;
if (atom_type != ATOM_DATA)
continue;
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- goto fail;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- goto fail;
- ret = read_int32(f, NULL); /* reserved */
- if (ret <= 0)
- goto fail;
+ skip_bytes(f, 8); /* version (1), flags (3), reserved (4) */
ret = -ERRNO_TO_PARA_ERROR(EINVAL);
if (subsize < header_size + 8 || subsize > UINT_MAX)
goto fail;
if (ret <= 0)
return ret;
if (version == 1) {
- ret = read_int64(f, NULL); /* creation-time */
- if (ret <= 0)
- return ret;
- ret = read_int64(f, NULL); /* modification-time */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 16); /* creation time (8), modification time (8) */
ret = read_int32(f, &t->time_scale);
if (ret <= 0)
return ret;
} else { //version == 0
uint32_t temp;
- ret = read_int32(f, NULL); /* creation-time */
- if (ret <= 0)
- return ret;
- ret = read_int32(f, NULL); /* modification-time */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 8); /* creation time (4), modification time (4) */
ret = read_int32(f, &t->time_scale);
if (ret <= 0)
return ret;
t->duration = (temp == (uint32_t) (-1))?
(uint64_t) (-1) : (uint64_t) (temp);
}
- ret = read_int16(f, NULL);
- if (ret <= 0)
- return ret;
- ret = read_int16(f, NULL);
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4);
return 1;
}
uint8_t atom_type;
uint8_t header_size = 0;
- ret = read_int8(f, NULL); /* version */
- if (ret <= 0)
- return ret;
- ret = read_int24(f, NULL); /* flags */
- if (ret <= 0)
- return ret;
+ skip_bytes(f, 4); /* version (1), flags (3) */
while (sumsize < (size - (header_size + 4))) {
ret = atom_read_header(f, &atom_type, &header_size, &subsize);
if (ret <= 0)
f->cb = cb;
while ((ret = atom_read_header(f, &atom_type, &header_size, &size)) > 0) {
- f->file_size += size;
f->last_atom = atom_type;
if (atom_type != ATOM_MOOV || size <= header_size) { /* skip */
set_position(f, get_position(f) + size - header_size);
continue;
return -ERRNO_TO_PARA_ERROR(errno);
}
- f->current_position += ret;
size -= ret;
}
return 1;
ret = write_data(f, "free", 4); /* rename old moov to free */
if (ret < 0)
goto free_moov;
- set_position(f, f->file_size); /* write new moov atom at EOF */
+ /* write new moov atom at EOF */
+ f->cb->seek(f->cb->user_data, 0, SEEK_END);
} else /* overwrite old moov atom */
set_position(f, f->moov_offset);
write_u32_be(buf, new_moov_size + 8);