summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorTomas Härdin <tomas.hardin@codemill.se>2011-05-18 13:48:02 +0200
committerAnton Khirnov <anton@khirnov.net>2011-07-13 11:57:51 +0200
commit67b1761fcbd8ddcfe7bdb47ace5f46435d8313fa (patch)
tree6453d14f9405209357419bf360a5abe9493ee29c /libavformat
parent90f2ee8cb4d2b135dd33128a94ad6cf126821472 (diff)
wav: keep parsing until EOF if the input is seekable and we know the size of the data tag
Signed-off-by: Anton Khirnov <anton@khirnov.net>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/wav.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/libavformat/wav.c b/libavformat/wav.c
index cf815ef3df..a8312e254e 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -296,7 +296,7 @@ static int wav_read_header(AVFormatContext *s,
AVStream *st;
WAVContext *wav = s->priv_data;
int ret, got_fmt = 0;
- int64_t next_tag_ofs;
+ int64_t next_tag_ofs, data_ofs = -1;
/* check RIFF header */
tag = avio_rl32(pb);
@@ -327,13 +327,13 @@ static int wav_read_header(AVFormatContext *s,
avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
}
-
for (;;) {
- if (pb->eof_reached)
- return -1;
size = next_tag(pb, &tag);
next_tag_ofs = avio_tell(pb) + size;
+ if (pb->eof_reached)
+ break;
+
switch (tag) {
case MKTAG('f', 'm', 't', ' '):
/* only parse the first 'fmt ' tag found */
@@ -350,26 +350,43 @@ static int wav_read_header(AVFormatContext *s,
return AVERROR_INVALIDDATA;
}
- goto break_loop;
+ if (rf64) {
+ next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
+ } else {
+ data_size = size;
+ next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
+ }
+
+ data_ofs = avio_tell(pb);
+
+ /* don't look for footer metadata if we can't seek or if we don't
+ * know where the data tag ends
+ */
+ if (!pb->seekable || (!rf64 && !size))
+ goto break_loop;
+ break;
case MKTAG('f','a','c','t'):
if (!sample_count)
sample_count = avio_rl32(pb);
break;
}
- avio_seek(pb, next_tag_ofs, SEEK_SET);
+
+ /* seek to next tag unless we know that we'll run into EOF */
+ if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
+ avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) {
+ break;
+ }
}
break_loop:
- if (rf64)
- size = data_size;
- if (size < 0)
- return -1;
- if (!size) {
- wav->data_end = INT64_MAX;
- } else
- wav->data_end= avio_tell(pb) + size;
+ if (data_ofs < 0) {
+ av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_seek(pb, data_ofs, SEEK_SET);
if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
- sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
+ sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
if (sample_count)
st->duration = sample_count;
return 0;