user specifyable maximum amount of memory to use for the index.
authorPaul Kelly <paul@stjohnspoint.co.uk>
Sun, 13 Jan 2008 13:33:37 +0000 (13:33 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 13 Jan 2008 13:33:37 +0000 (13:33 +0000)
patch by Paul Kelly  paul stjohnspoint co uk
with some changes by me

Originally committed as revision 11521 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/avformat.h
libavformat/mpeg.c
libavformat/utils.c

index e303d48..de62231 100644 (file)
@@ -21,8 +21,8 @@
 #ifndef FFMPEG_AVFORMAT_H
 #define FFMPEG_AVFORMAT_H
 
-#define LIBAVFORMAT_VERSION_INT ((52<<16)+(3<<8)+0)
-#define LIBAVFORMAT_VERSION     52.3.0
+#define LIBAVFORMAT_VERSION_INT ((52<<16)+(4<<8)+0)
+#define LIBAVFORMAT_VERSION     52.4.0
 #define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT
 
 #define LIBAVFORMAT_IDENT       "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
@@ -477,6 +477,18 @@ typedef struct AVFormatContext {
      * demuxing: set by user
      */
     enum CodecID subtitle_codec_id;
+
+    /**
+     * Maximum amount of memory in bytes to use per stream for the index.
+     * If the needed index exceeds this size entries will be discarded as
+     * needed to maintain a smaller size. This can lead to slower or less
+     * accurate seeking (depends on demuxer).
+     * Demuxers for which a full in memory index is mandatory will ignore
+     * this.
+     * muxing  : unused
+     * demuxing: set by user
+     */
+    unsigned int max_index_size;
 } AVFormatContext;
 
 typedef struct AVPacketList {
@@ -735,6 +747,15 @@ int av_find_default_stream_index(AVFormatContext *s);
  */
 int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
 
+/**
+ * Ensures the index uses less memory than the maximum specified in
+ * AVFormatContext.max_index_size, by discarding entries if it grows
+ * too large.
+ * This function is not part of the public API and should only be called
+ * by demuxers.
+ */
+void ff_reduce_index(AVFormatContext *s, int stream_index);
+
 /**
  * Add a index entry into a sorted list updateing if it is already there.
  *
index d044d07..aca9db2 100644 (file)
@@ -386,6 +386,7 @@ static int mpegps_read_pes_header(AVFormatContext *s,
         int i;
         for(i=0; i<s->nb_streams; i++){
             if(startcode == s->streams[i]->id) {
+                ff_reduce_index(s, i);
                 av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
             }
         }
index ea47bcf..d116e84 100644 (file)
@@ -324,6 +324,7 @@ static const AVOption options[]={
 {"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E},
 {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D},
 {"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, 0, 0, 0, D},
+{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), FF_OPT_TYPE_INT, INT_MAX, 0, INT_MAX, D},
 {NULL},
 };
 
@@ -791,6 +792,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                     compute_pkt_fields(s, st, st->parser, pkt);
 
                     if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & PKT_FLAG_KEY){
+                        ff_reduce_index(s, st->index);
                         av_add_index_entry(st, st->parser->frame_offset, pkt->dts,
                                            0, 0, AVINDEX_KEYFRAME);
                     }
@@ -1008,6 +1010,19 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
     }
 }
 
+void ff_reduce_index(AVFormatContext *s, int stream_index)
+{
+    AVStream *st= s->streams[stream_index];
+    unsigned int max_entries= s->max_index_size / sizeof(AVIndexEntry);
+
+    if((unsigned)st->nb_index_entries >= max_entries){
+        int i;
+        for(i=0; 2*i<st->nb_index_entries; i++)
+            st->index_entries[i]= st->index_entries[2*i];
+        st->nb_index_entries= i;
+    }
+}
+
 int av_add_index_entry(AVStream *st,
                             int64_t pos, int64_t timestamp, int size, int distance, int flags)
 {