From 987e857f638bff63f11905d06466e198a9765f65 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Tue, 9 Mar 2010 00:46:26 +0000 Subject: [PATCH] Preallocate index entries in mov demuxer, huge speedup Originally committed as revision 22363 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/mov.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 3ff046b93..93766eeb2 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); -- 2.11.0