diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2009-03-16 13:03:23 +0000 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2009-03-16 13:03:23 +0000 |
commit | 2d6f3014701d891b5a461fb86d127c53ca410943 (patch) | |
tree | b26e166dfabfce11a1f9d416c360803ff2d55abe /libavformat/rmdec.c | |
parent | aa0bd9929519e9d960e8736a853012699899b9f1 (diff) | |
download | ffmpeg-2d6f3014701d891b5a461fb86d127c53ca410943.tar.gz |
Parse index chunk so that seeking in modern .rm files becomes a lot faster.
Has been tested against streamed / non-seekable input and passes make
seektest. See "[PATCH] rmdec.c: parse INDX chunk" thread on mailinglist.
Originally committed as revision 18013 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/rmdec.c')
-rw-r--r-- | libavformat/rmdec.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 90f07a4f09..b4e051b279 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -292,6 +292,49 @@ skip: return 0; } +/** this function assumes that the demuxer has already seeked to the start + * of the INDX chunk, and will bail out if not. */ +static int rm_read_index(AVFormatContext *s) +{ + ByteIOContext *pb = s->pb; + unsigned int size, n_pkts, str_id, next_off, n, pos, pts; + AVStream *st; + + do { + if (get_le32(pb) != MKTAG('I','N','D','X')) + return -1; + size = get_be32(pb); + if (size < 20) + return -1; + url_fskip(pb, 2); + n_pkts = get_be32(pb); + str_id = get_be16(pb); + next_off = get_be32(pb); + for (n = 0; n < s->nb_streams; n++) + if (s->streams[n]->id == str_id) { + st = s->streams[n]; + break; + } + if (n == s->nb_streams) + goto skip; + + for (n = 0; n < n_pkts; n++) { + url_fskip(pb, 2); + pts = get_be32(pb); + pos = get_be32(pb); + url_fskip(pb, 4); /* packet no. */ + + av_add_index_entry(st, pos, pts, 0, 0, AVINDEX_KEYFRAME); + } + +skip: + if (next_off && url_ftell(pb) != next_off && + url_fseek(pb, next_off, SEEK_SET) < 0) + return -1; + } while (next_off); + + return 0; +} static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap) { @@ -314,6 +357,7 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) unsigned int tag; int tag_size; unsigned int start_time, duration; + unsigned int data_off = 0, indx_off = 0; char buf[128]; int flags = 0; @@ -357,8 +401,8 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) get_be32(pb); /* nb packets */ get_be32(pb); /* duration */ get_be32(pb); /* preroll */ - get_be32(pb); /* index offset */ - get_be32(pb); /* data offset */ + indx_off = get_be32(pb); /* index offset */ + data_off = get_be32(pb); /* data offset */ get_be16(pb); /* nb streams */ flags = get_be16(pb); /* flags */ break; @@ -400,6 +444,14 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) if (!rm->nb_packets && (flags & 4)) rm->nb_packets = 3600 * 25; get_be32(pb); /* next data header */ + + if (!data_off) + data_off = url_ftell(pb) - 18; + if (indx_off && url_fseek(pb, indx_off, SEEK_SET) >= 0) { + rm_read_index(s); + url_fseek(pb, data_off + 18, SEEK_SET); + } + return 0; } |