patch by Paul Kelly paul stjohnspoint co uk with some changes by me Originally committed as revision 11521 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -21,8 +21,8 @@ | |||||
| #ifndef FFMPEG_AVFORMAT_H | #ifndef FFMPEG_AVFORMAT_H | ||||
| #define 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_BUILD LIBAVFORMAT_VERSION_INT | ||||
| #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | ||||
| @@ -477,6 +477,18 @@ typedef struct AVFormatContext { | |||||
| * demuxing: set by user | * demuxing: set by user | ||||
| */ | */ | ||||
| enum CodecID subtitle_codec_id; | 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; | } AVFormatContext; | ||||
| typedef struct AVPacketList { | 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); | 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. | * Add a index entry into a sorted list updateing if it is already there. | ||||
| * | * | ||||
| @@ -386,6 +386,7 @@ static int mpegps_read_pes_header(AVFormatContext *s, | |||||
| int i; | int i; | ||||
| for(i=0; i<s->nb_streams; i++){ | for(i=0; i<s->nb_streams; i++){ | ||||
| if(startcode == s->streams[i]->id) { | 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? */); | av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); | ||||
| } | } | ||||
| } | } | ||||
| @@ -324,6 +324,7 @@ static const AVOption options[]={ | |||||
| {"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E}, | {"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}, | {"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}, | {"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}, | {NULL}, | ||||
| }; | }; | ||||
| @@ -791,6 +792,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) | |||||
| compute_pkt_fields(s, st, st->parser, pkt); | compute_pkt_fields(s, st, st->parser, pkt); | ||||
| if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & PKT_FLAG_KEY){ | 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, | av_add_index_entry(st, st->parser->frame_offset, pkt->dts, | ||||
| 0, 0, AVINDEX_KEYFRAME); | 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, | int av_add_index_entry(AVStream *st, | ||||
| int64_t pos, int64_t timestamp, int size, int distance, int flags) | int64_t pos, int64_t timestamp, int size, int distance, int flags) | ||||
| { | { | ||||