[SCM] libav/experimental: Preallocate index entries in mov demuxer, huge speedup

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jun 30 17:03:45 UTC 2013


The following commit has been merged in the experimental branch:
commit 987e857f638bff63f11905d06466e198a9765f65
Author: Baptiste Coudurier <baptiste.coudurier at gmail.com>
Date:   Tue Mar 9 00:46:26 2010 +0000

    Preallocate index entries in mov demuxer, huge speedup
    
    Originally committed as revision 22363 to svn://svn.ffmpeg.org/ffmpeg/trunk

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 3ff046b..93766ee 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);

-- 
Libav/FFmpeg packaging



More information about the pkg-multimedia-commits mailing list