aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/rmdec.c
diff options
context:
space:
mode:
authorRonald S. Bultje <rsbultje@gmail.com>2009-03-16 13:03:23 +0000
committerRonald S. Bultje <rsbultje@gmail.com>2009-03-16 13:03:23 +0000
commit2d6f3014701d891b5a461fb86d127c53ca410943 (patch)
treeb26e166dfabfce11a1f9d416c360803ff2d55abe /libavformat/rmdec.c
parentaa0bd9929519e9d960e8736a853012699899b9f1 (diff)
downloadffmpeg-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.c56
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;
}