aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mov.c
diff options
context:
space:
mode:
authorBaptiste Coudurier <baptiste.coudurier@gmail.com>2010-03-09 00:46:26 +0000
committerBaptiste Coudurier <baptiste.coudurier@gmail.com>2010-03-09 00:46:26 +0000
commit987e857f638bff63f11905d06466e198a9765f65 (patch)
treec62332fd58266154043754697d95f3851eb64218 /libavformat/mov.c
parent1307463d5259a80fdbb43f50434eb9ba37c50d30 (diff)
downloadffmpeg-987e857f638bff63f11905d06466e198a9765f65.tar.gz
Preallocate index entries in mov demuxer, huge speedup
Originally committed as revision 22363 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r--libavformat/mov.c71
1 files changed, 61 insertions, 10 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 3ff046b934..93766eeb27 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1462,6 +1462,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
current_dts -= sc->dts_shift;
+ if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries))
+ return;
+ st->index_entries = av_malloc(sc->sample_count*sizeof(*st->index_entries));
+ if (!st->index_entries)
+ return;
+ st->index_entries_allocated_size = sc->sample_count*sizeof(*st->index_entries);
+
for (i = 0; i < sc->chunk_count; i++) {
current_offset = sc->chunk_offsets[i];
if (stsc_index + 1 < sc->stsc_count &&
@@ -1488,8 +1495,12 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
if(sc->pseudo_stream_id == -1 ||
sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
- av_add_index_entry(st, current_offset, current_dts, sample_size, distance,
- keyframe ? AVINDEX_KEYFRAME : 0);
+ AVIndexEntry *e = &st->index_entries[st->nb_index_entries++];
+ e->pos = current_offset;
+ e->timestamp = current_dts;
+ e->size = sample_size;
+ e->min_distance = distance;
+ e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
"size %d, distance %d, keyframe %d\n", st->index, current_sample,
current_offset, current_dts, sample_size, distance, keyframe);
@@ -1510,21 +1521,52 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
if (st->duration > 0)
st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration;
} else {
- for (i = 0; i < sc->chunk_count; i++) {
- unsigned chunk_samples;
+ unsigned chunk_samples, total = 0;
- current_offset = sc->chunk_offsets[i];
- if (stsc_index + 1 < sc->stsc_count &&
- i + 1 == sc->stsc_data[stsc_index + 1].first)
- stsc_index++;
- chunk_samples = sc->stsc_data[stsc_index].count;
+ // compute total chunk count
+ for (i = 0; i < sc->stsc_count; i++) {
+ unsigned count, chunk_count;
+ chunk_samples = sc->stsc_data[i].count;
if (sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
return;
}
+ if (sc->samples_per_frame >= 160) { // gsm
+ count = chunk_samples / sc->samples_per_frame;
+ } else if (sc->samples_per_frame > 1) {
+ unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
+ count = (chunk_samples+samples-1) / samples;
+ } else {
+ count = (chunk_samples+1023) / 1024;
+ }
+
+ if (i < sc->stsc_count - 1)
+ chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
+ else
+ chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
+ total += chunk_count * count;
+ }
+
+ dprintf(mov->fc, "chunk count %d\n", total);
+ if (total >= UINT_MAX / sizeof(*st->index_entries))
+ return;
+ st->index_entries = av_malloc(total*sizeof(*st->index_entries));
+ if (!st->index_entries)
+ return;
+ st->index_entries_allocated_size = total*sizeof(*st->index_entries);
+
+ // populate index
+ for (i = 0; i < sc->chunk_count; i++) {
+ current_offset = sc->chunk_offsets[i];
+ if (stsc_index + 1 < sc->stsc_count &&
+ i + 1 == sc->stsc_data[stsc_index + 1].first)
+ stsc_index++;
+ chunk_samples = sc->stsc_data[stsc_index].count;
+
while (chunk_samples > 0) {
+ AVIndexEntry *e;
unsigned size, samples;
if (sc->samples_per_frame >= 160) { // gsm
@@ -1541,7 +1583,16 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
}
}
- av_add_index_entry(st, current_offset, current_dts, size, 0, AVINDEX_KEYFRAME);
+ if (st->nb_index_entries >= total) {
+ av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %d\n", total);
+ return;
+ }
+ e = &st->index_entries[st->nb_index_entries++];
+ e->pos = current_offset;
+ e->timestamp = current_dts;
+ e->size = size;
+ e->min_distance = 0;
+ e->flags = AVINDEX_KEYFRAME;
dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", "
"size %d, duration %d\n", st->index, i, current_offset, current_dts,
size, samples);