summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/isom.h1
-rw-r--r--libavformat/mov.c92
2 files changed, 58 insertions, 35 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h
index ff009b0896..fdd98c28f5 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -137,6 +137,7 @@ typedef struct MOVStreamContext {
unsigned int stts_count;
MOVStts *stts_data;
unsigned int ctts_count;
+ unsigned int ctts_allocated_size;
MOVStts *ctts_data;
unsigned int stsc_count;
MOVStsc *stsc_data;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index a14c9f182b..876f48d912 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -74,6 +74,8 @@ typedef struct MOVParseTableEntry {
static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
static int mov_read_mfra(MOVContext *c, AVIOContext *f);
+static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
+ int count, int duration);
static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
unsigned len, const char *key)
@@ -2711,7 +2713,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVStream *st;
MOVStreamContext *sc;
- unsigned int i, entries, ctts_count = 0;
+ unsigned int i, j, entries, ctts_count = 0;
if (c->fc->nb_streams < 1)
return 0;
@@ -2729,7 +2731,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
return AVERROR_INVALIDDATA;
av_freep(&sc->ctts_data);
- sc->ctts_data = av_realloc(NULL, entries * sizeof(*sc->ctts_data));
+ sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
if (!sc->ctts_data)
return AVERROR(ENOMEM);
@@ -2744,9 +2746,9 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
continue;
}
- sc->ctts_data[ctts_count].count = count;
- sc->ctts_data[ctts_count].duration = duration;
- ctts_count++;
+ /* Expand entries such that we have a 1-1 mapping with samples. */
+ for (j = 0; j < count; j++)
+ add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size, 1, duration);
av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
count, duration);
@@ -3049,7 +3051,6 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
int64_t index;
int64_t index_ctts_count;
int flags;
- unsigned int ctts_allocated_size = 0;
int64_t start_dts = 0;
int64_t edit_list_media_time_dts = 0;
int64_t edit_list_start_encountered = 0;
@@ -3084,6 +3085,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
msc->ctts_count = 0;
msc->ctts_index = 0;
msc->ctts_sample = 0;
+ msc->ctts_allocated_size = 0;
// If the dts_shift is positive (in case of negative ctts values in mov),
// then negate the DTS by dts_shift
@@ -3193,7 +3195,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
ctts_sample_old++;
if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
- &ctts_allocated_size,
+ &msc->ctts_allocated_size,
ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
ctts_data_old[ctts_index_old].duration) == -1) {
av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
@@ -3292,7 +3294,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
if (ctts_data_old && ctts_sample_old != 0) {
if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
- &ctts_allocated_size,
+ &msc->ctts_allocated_size,
ctts_sample_old - edit_list_start_ctts_sample,
ctts_data_old[ctts_index_old].duration) == -1) {
av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
@@ -4262,7 +4264,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int64_t dts;
int data_offset = 0;
unsigned entries, first_sample_flags = frag->flags;
- int flags, distance, i, err, old_nb_index_entries;
+ int flags, distance, i;
for (i = 0; i < c->fc->nb_streams; i++) {
if (c->fc->streams[i]->id == frag->track_id) {
@@ -4290,21 +4292,20 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (!sc->ctts_count && sc->sample_count)
{
/* Complement ctts table if moov atom doesn't have ctts atom. */
- ctts_data = av_realloc(NULL, sizeof(*sc->ctts_data));
+ ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, sizeof(*sc->ctts_data) * sc->sample_count);
if (!ctts_data)
return AVERROR(ENOMEM);
+ /* Don't use a count greater than 1 here since it will leave a gap in
+ * the ctts index which the code below relies on being sequential. */
sc->ctts_data = ctts_data;
- sc->ctts_data[sc->ctts_count].count = sc->sample_count;
- sc->ctts_data[sc->ctts_count].duration = 0;
- sc->ctts_count++;
+ for (i = 0; i < sc->sample_count; i++) {
+ sc->ctts_data[sc->ctts_count].count = 1;
+ sc->ctts_data[sc->ctts_count].duration = 0;
+ sc->ctts_count++;
+ }
}
if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
return AVERROR_INVALIDDATA;
- if ((err = av_reallocp_array(&sc->ctts_data, entries + sc->ctts_count,
- sizeof(*sc->ctts_data))) < 0) {
- sc->ctts_count = 0;
- return err;
- }
if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
dts = sc->track_end - sc->time_offset;
@@ -4315,26 +4316,28 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
unsigned sample_size = frag->size;
int sample_flags = i ? frag->flags : first_sample_flags;
unsigned sample_duration = frag->duration;
+ unsigned ctts_duration = 0;
int keyframe = 0;
+ int ctts_index = 0;
+ int old_nb_index_entries = st->nb_index_entries;
if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
- sc->ctts_data[sc->ctts_count].count = 1;
- sc->ctts_data[sc->ctts_count].duration = (flags & MOV_TRUN_SAMPLE_CTS) ?
- avio_rb32(pb) : 0;
- mov_update_dts_shift(sc, sc->ctts_data[sc->ctts_count].duration);
+ if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
+
+ mov_update_dts_shift(sc, ctts_duration);
if (frag->time != AV_NOPTS_VALUE) {
if (c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
int64_t pts = frag->time;
av_log(c->fc, AV_LOG_DEBUG, "found frag time %"PRId64
" sc->dts_shift %d ctts.duration %d"
" sc->time_offset %"PRId64" flags & MOV_TRUN_SAMPLE_CTS %d\n", pts,
- sc->dts_shift, sc->ctts_data[sc->ctts_count].duration,
+ sc->dts_shift, ctts_duration,
sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
dts = pts - sc->dts_shift;
if (flags & MOV_TRUN_SAMPLE_CTS) {
- dts -= sc->ctts_data[sc->ctts_count].duration;
+ dts -= ctts_duration;
} else {
dts -= sc->time_offset;
}
@@ -4346,7 +4349,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
}
frag->time = AV_NOPTS_VALUE;
}
- sc->ctts_count++;
+
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
keyframe = 1;
else
@@ -4355,19 +4358,38 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
if (keyframe)
distance = 0;
- old_nb_index_entries = st->nb_index_entries;
- err = av_add_index_entry(st, offset, dts, sample_size, distance,
- keyframe ? AVINDEX_KEYFRAME : 0);
- if (err < 0) {
+ ctts_index = av_add_index_entry(st, offset, dts, sample_size, distance,
+ keyframe ? AVINDEX_KEYFRAME : 0);
+ if (ctts_index >= 0 && old_nb_index_entries < st->nb_index_entries) {
+ unsigned int size_needed = st->nb_index_entries * sizeof(*sc->ctts_data);
+ unsigned int request_size = size_needed > sc->ctts_allocated_size ?
+ FFMAX(size_needed, 2 * sc->ctts_allocated_size) : size_needed;
+ ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, request_size);
+ if (!ctts_data) {
+ av_freep(&sc->ctts_data);
+ return AVERROR(ENOMEM);
+ }
+
+ sc->ctts_data = ctts_data;
+ if (ctts_index != old_nb_index_entries) {
+ memmove(sc->ctts_data + ctts_index + 1, sc->ctts_data + ctts_index,
+ sizeof(*sc->ctts_data) * (sc->ctts_count - ctts_index));
+ if (ctts_index <= sc->current_sample) {
+ // if we inserted a new item before the current sample, move the
+ // counter ahead so it is still pointing to the same sample.
+ sc->current_sample++;
+ }
+ }
+
+ sc->ctts_data[ctts_index].count = 1;
+ sc->ctts_data[ctts_index].duration = ctts_duration;
+ sc->ctts_count++;
+ } else {
av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
- } else if (err <= sc->current_sample && err + 1 != st->nb_index_entries &&
- st->nb_index_entries != old_nb_index_entries) {
- // if we inserted a new item before the current sample, move the
- // counter ahead so it is still pointing to the same sample.
- sc->current_sample++;
}
+
av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
- "size %u, distance %d, keyframe %d\n", st->index, err,
+ "size %u, distance %d, keyframe %d\n", st->index, ctts_index,
offset, dts, sample_size, distance, keyframe);
distance++;
dts += sample_duration;