summaryrefslogtreecommitdiff
path: root/libavformat/mov.c
diff options
context:
space:
mode:
authorClément Bœsch <clement@stupeflix.com>2014-11-12 15:42:17 +0100
committerClément Bœsch <clement@stupeflix.com>2015-01-02 11:38:21 +0100
commit55faf56c7256f5c0afa7d90140b6595005529d4b (patch)
tree1fda16b375fcfa2ae29147239ba3637df6c4efcb /libavformat/mov.c
parent75cc57f73f9aee8721a101b3c6ef85312ea9e54c (diff)
avformat/mov: move edit list heuristics into mov_build_index()
mov_read_elst() is now only responsible from storing the table in a data structure; this is consistent with other table readers functions.
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r--libavformat/mov.c78
1 files changed, 48 insertions, 30 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 4cfeb36dc6..a509932618 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2268,11 +2268,32 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
unsigned int i, j;
uint64_t stream_size = 0;
+ if (sc->elst_count) {
+ int i, edit_start_index = 0, unsupported = 0;
+ int64_t empty_duration = 0; // empty duration of the first edit list entry
+ int64_t start_time = 0; // start time of the media
+
+ for (i = 0; i < sc->elst_count; i++) {
+ const MOVElst *e = &sc->elst_data[i];
+ if (i == 0 && e->time == -1) {
+ /* if empty, the first entry is the start time of the stream
+ * relative to the presentation itself */
+ empty_duration = e->duration;
+ edit_start_index = 1;
+ } else if (i == edit_start_index && e->time >= 0) {
+ start_time = e->time;
+ } else
+ unsupported = 1;
+ }
+ if (unsupported)
+ av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
+ "a/v desync might occur, patch welcome\n");
+
/* adjust first dts according to edit list */
- if ((sc->empty_duration || sc->start_time) && mov->time_scale > 0) {
- if (sc->empty_duration)
- sc->empty_duration = av_rescale(sc->empty_duration, sc->time_scale, mov->time_scale);
- sc->time_offset = sc->start_time - sc->empty_duration;
+ if ((empty_duration || start_time) && mov->time_scale > 0) {
+ if (empty_duration)
+ empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
+ sc->time_offset = start_time - empty_duration;
current_dts = -sc->time_offset;
if (sc->ctts_count>0 && sc->stts_count>0 &&
sc->ctts_data[0].duration / FFMAX(sc->stts_data[0].duration, 1) > 16) {
@@ -2282,6 +2303,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
st->codec->has_b_frames = 1;
}
}
+ }
/* only use old uncompressed audio chunk demuxing when stts specifies it */
if (!(st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
@@ -2626,6 +2648,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_freep(&sc->keyframes);
av_freep(&sc->stts_data);
av_freep(&sc->stps_data);
+ av_freep(&sc->elst_data);
av_freep(&sc->rap_group);
return 0;
@@ -3190,8 +3213,7 @@ free_and_return:
static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
MOVStreamContext *sc;
- int i, edit_count, version, edit_start_index = 0;
- int unsupported = 0;
+ int i, edit_count, version;
if (c->fc->nb_streams < 1 || c->ignore_editlist)
return 0;
@@ -3201,37 +3223,32 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
avio_rb24(pb); /* flags */
edit_count = avio_rb32(pb); /* entries */
- if ((uint64_t)edit_count*12+8 > atom.size)
- return AVERROR_INVALIDDATA;
+ if (!edit_count)
+ return 0;
+ if (sc->elst_data)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
+ av_free(sc->elst_data);
+ sc->elst_count = 0;
+ sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
+ if (!sc->elst_data)
+ return AVERROR(ENOMEM);
av_dlog(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count);
- for (i=0; i<edit_count; i++){
- int64_t time;
- int64_t duration;
- int rate;
+ for (i = 0; i < edit_count && !pb->eof_reached; i++) {
+ MOVElst *e = &sc->elst_data[i];
+
if (version == 1) {
- duration = avio_rb64(pb);
- time = avio_rb64(pb);
+ e->duration = avio_rb64(pb);
+ e->time = avio_rb64(pb);
} else {
- duration = avio_rb32(pb); /* segment duration */
- time = (int32_t)avio_rb32(pb); /* media time */
+ e->duration = avio_rb32(pb); /* segment duration */
+ e->time = (int32_t)avio_rb32(pb); /* media time */
}
- rate = avio_rb32(pb);
- if (i == 0 && time == -1) {
- sc->empty_duration = duration;
- edit_start_index = 1;
- } else if (i == edit_start_index && time >= 0)
- sc->start_time = time;
- else
- unsupported = 1;
-
+ e->rate = avio_rb32(pb) / 65536.0;
av_dlog(c->fc, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
- duration, time, rate / 65536.0);
+ e->duration, e->time, e->rate);
}
-
- if (unsupported)
- av_log(c->fc, AV_LOG_WARNING, "multiple edit list entries, "
- "a/v desync might occur, patch welcome\n");
+ sc->elst_count = i;
return 0;
}
@@ -3746,6 +3763,7 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&sc->keyframes);
av_freep(&sc->stts_data);
av_freep(&sc->stps_data);
+ av_freep(&sc->elst_data);
av_freep(&sc->rap_group);
av_freep(&sc->display_matrix);
}