case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
case MKTAG( 'l','o','c','i'):
return mov_metadata_loci(c, pb, atom.size);
+ case MKTAG( 'm','a','n','u'): key = "make"; break;
+ case MKTAG( 'm','o','d','l'): key = "model"; break;
case MKTAG( 'p','c','s','t'): key = "podcast";
parse = mov_metadata_int8_no_padding; break;
case MKTAG( 'p','g','a','p'): key = "gapless_playback";
int ret = mov_read_covr(c, pb, data_type, str_size);
if (ret < 0) {
av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
+ return ret;
}
+ atom.size -= str_size;
+ if (atom.size > 8)
+ goto retry;
return ret;
} else if (!key && c->found_hdlr_mdta && c->meta_keys) {
uint32_t index = AV_RB32(&atom.type);
return mov_finalize_stsd_codec(c, pb, st, sc);
fail:
+ if (sc->extradata) {
+ int j;
+ for (j = 0; j < sc->stsd_count; j++)
+ av_freep(&sc->extradata[j]);
+ }
+
av_freep(&sc->extradata);
av_freep(&sc->extradata_size);
return ret;
}
sc->stsc_count = i;
+ for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
+ if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
+ (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
+ sc->stsc_data[i].first < 1 ||
+ sc->stsc_data[i].count < 1 ||
+ sc->stsc_data[i].id < 1) {
+ av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id);
+ if (i+1 >= sc->stsc_count || sc->stsc_data[i+1].first < 2)
+ return AVERROR_INVALIDDATA;
+ // We replace this entry by the next valid
+ sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
+ sc->stsc_data[i].count = sc->stsc_data[i+1].count;
+ sc->stsc_data[i].id = sc->stsc_data[i+1].id;
+ }
+ }
if (pb->eof_reached) {
av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
}
/* Compute the samples value for the stsc entry at the given index. */
-static inline int mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
+static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
{
int chunk_count;
else
chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
- return sc->stsc_data[index].count * chunk_count;
+ return sc->stsc_data[index].count * (int64_t)chunk_count;
}
static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
for (i = 0; i < entries && !pb->eof_reached; i++) {
int sample_duration;
unsigned int sample_count;
- unsigned min_entries = FFMIN(FFMAX(i, 1024 * 1024), entries);
+ unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
min_entries * sizeof(*sc->stts_data));
if (!stts_data) {
&& total_sample_count > 100
&& sample_duration/10 > duration / total_sample_count)
sample_duration = duration / total_sample_count;
- duration+=(int64_t)sample_duration*sample_count;
+ duration+=(int64_t)sample_duration*(uint64_t)sample_count;
total_sample_count+=sample_count;
}
sc->stts_count = i;
- sc->duration_for_fps += duration;
- sc->nb_frames_for_fps += total_sample_count;
+ if (duration > 0 &&
+ duration <= INT64_MAX - sc->duration_for_fps &&
+ total_sample_count <= INT64_MAX - sc->nb_frames_for_fps
+ ) {
+ sc->duration_for_fps += duration;
+ sc->nb_frames_for_fps += total_sample_count;
+ }
if (pb->eof_reached) {
av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
FFMAX(min_size_needed, 2 * (*allocated_size)) :
min_size_needed;
- if((unsigned)(*ctts_count) + 1 >= UINT_MAX / sizeof(MOVStts))
+ if((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1)
return -1;
ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);
int64_t edit_list_start_ctts_sample = 0;
int64_t curr_cts;
int64_t curr_ctts = 0;
- int64_t min_corrected_pts = -1;
int64_t empty_edits_sum_duration = 0;
int64_t edit_list_index = 0;
int64_t index;
msc->ctts_sample = 0;
msc->ctts_allocated_size = 0;
+ // Reinitialize min_corrected_pts so that it can be computed again.
+ msc->min_corrected_pts = -1;
+
// If the dts_shift is positive (in case of negative ctts values in mov),
// then negate the DTS by dts_shift
if (msc->dts_shift > 0) {
}
}
} else {
- if (min_corrected_pts < 0) {
- min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
+ if (msc->min_corrected_pts < 0) {
+ msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
} else {
- min_corrected_pts = FFMIN(min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
+ msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
}
if (edit_list_start_encountered == 0) {
edit_list_start_encountered = 1;
}
}
}
- // If there are empty edits, then min_corrected_pts might be positive intentionally. So we subtract the
- // sum duration of emtpy edits here.
- min_corrected_pts -= empty_edits_sum_duration;
+ // If there are empty edits, then msc->min_corrected_pts might be positive
+ // intentionally. So we subtract the sum duration of emtpy edits here.
+ msc->min_corrected_pts -= empty_edits_sum_duration;
// If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
// dts by that amount to make the first pts zero.
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && min_corrected_pts > 0) {
- av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", min_corrected_pts);
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && msc->min_corrected_pts > 0) {
+ av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
for (i = 0; i < st->nb_index_entries; ++i) {
- st->index_entries[i].timestamp -= min_corrected_pts;
+ st->index_entries[i].timestamp -= msc->min_corrected_pts;
}
}
if (empty_duration)
empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
sc->time_offset = start_time - empty_duration;
+ sc->min_corrected_pts = start_time;
if (!mov->advanced_editlist)
current_dts = -sc->time_offset;
}
av_free(ctts_data_old);
return;
}
+
+ memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);
+
for (i = 0; i < ctts_count_old &&
sc->ctts_count < sc->sample_count; i++)
for (j = 0; j < ctts_data_old[i].count &&
st->index);
return 0;
}
+ if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
+ av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
+ st->index);
+ return AVERROR_INVALIDDATA;
+ }
fix_timescale(c, sc);
return AVERROR_INVALIDDATA;
}
sc = st->priv_data;
- if (sc->pseudo_stream_id + 1 != frag->stsd_id)
+ if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
return 0;
version = avio_r8(pb);
avio_rb24(pb); /* flags */
int64_t prev_dts = AV_NOPTS_VALUE;
int next_frag_index = -1, index_entry_pos;
size_t requested_size;
+ size_t old_ctts_allocated_size;
AVIndexEntry *new_entries;
MOVFragmentStreamInfo * frag_stream_info;
st->index_entries= new_entries;
requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
+ old_ctts_allocated_size = sc->ctts_allocated_size;
ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
requested_size);
if (!ctts_data)
// In case there were samples without ctts entries, ensure they get
// zero valued entries. This ensures clips which mix boxes with and
// without ctts entries don't pickup uninitialized data.
- memset(sc->ctts_data + sc->ctts_count, 0,
- (st->nb_index_entries - sc->ctts_count) * sizeof(*sc->ctts_data));
+ memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
+ sc->ctts_allocated_size - old_ctts_allocated_size);
if (index_entry_pos < st->nb_index_entries) {
// Make hole in index_entries and ctts_data for new samples
dts += sample_duration;
offset += sample_size;
sc->data_size += sample_size;
- sc->duration_for_fps += sample_duration;
- sc->nb_frames_for_fps ++;
+
+ if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
+ 1 <= INT64_MAX - sc->nb_frames_for_fps
+ ) {
+ sc->duration_for_fps += sample_duration;
+ sc->nb_frames_for_fps ++;
+ }
}
if (i < entries) {
// EOF found before reading all entries. Fix the hole this would
projection = AV_SPHERICAL_EQUIRECTANGULAR;
break;
default:
- av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n");
+ av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
return 0;
}
int sample, time_sample, ret;
unsigned int i;
- timestamp -= sc->time_offset;
+ // Here we consider timestamp to be PTS, hence try to offset it so that we
+ // can search over the DTS timeline.
+ timestamp -= (sc->min_corrected_pts + sc->dts_shift);
ret = mov_seek_fragment(s, st, timestamp);
if (ret < 0)
/* adjust stsd index */
time_sample = 0;
for (i = 0; i < sc->stsc_count; i++) {
- int next = time_sample + mov_get_stsc_samples(sc, i);
+ int64_t next = time_sample + mov_get_stsc_samples(sc, i);
if (next > sc->current_sample) {
sc->stsc_index = i;
sc->stsc_sample = sc->current_sample - time_sample;
break;
}
+ av_assert0(next == (int)next);
time_sample = next;
}