diff options
author | Alexander Strasser <eclipse7@gmx.net> | 2013-08-13 18:36:21 +0200 |
---|---|---|
committer | Alexander Strasser <eclipse7@gmx.net> | 2013-08-14 22:05:41 +0200 |
commit | dc2e4c2e532b80565f5fbacd3a24a6db7567c257 (patch) | |
tree | ef633336a8a09383187118f4a2734bbb634f7360 | |
parent | dabfa80ce27f1e93e3d265db9d3f38a819e144af (diff) | |
download | ffmpeg-streaming-dc2e4c2e532b80565f5fbacd3a24a6db7567c257.zip ffmpeg-streaming-dc2e4c2e532b80565f5fbacd3a24a6db7567c257.tar.gz |
lavf/wavdec: Fix seeking in files with unaligned offsets
A file with a prepended ID3 tag of an uneven length was found
in the wild.
Check if the wav data starts at an uneven offset and use that
information to correct the seeking calculation in wav_seek_tag,
which used to only seek to even byte positions.
Regression since ac87eaf856e0fb51917266b899bb15d19b907baf
Signed-off-by: Alexander Strasser <eclipse7@gmx.net>
-rw-r--r-- | libavformat/wavdec.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index adf41ec..d5b3b9e 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -54,6 +54,7 @@ typedef struct WAVDemuxContext { int spdif; int smv_cur_pt; int smv_given_first; + int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended } WAVDemuxContext; #if CONFIG_WAV_DEMUXER @@ -64,16 +65,16 @@ static int64_t next_tag(AVIOContext *pb, uint32_t *tag) return avio_rl32(pb); } -/* RIFF chunks are always on a even offset. */ -static int64_t wav_seek_tag(AVIOContext *s, int64_t offset, int whence) +/* RIFF chunks are always at even offsets relative to where they start. */ +static int64_t wav_seek_tag(WAVDemuxContext * wav, AVIOContext *s, int64_t offset, int whence) { - offset += offset < INT64_MAX && offset & 1; + offset += offset < INT64_MAX && offset + wav->unaligned & 1; return avio_seek(s, offset, whence); } /* return the size of the found tag */ -static int64_t find_tag(AVIOContext *pb, uint32_t tag1) +static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1) { unsigned int tag; int64_t size; @@ -84,7 +85,7 @@ static int64_t find_tag(AVIOContext *pb, uint32_t tag1) size = next_tag(pb, &tag); if (tag == tag1) break; - wav_seek_tag(pb, size, SEEK_CUR); + wav_seek_tag(wav, pb, size, SEEK_CUR); } return size; } @@ -247,6 +248,8 @@ static int wav_read_header(AVFormatContext *s) int ret, got_fmt = 0; int64_t next_tag_ofs, data_ofs = -1; + wav->unaligned = avio_tell(s->pb) & 1; + wav->smv_data_ofs = -1; /* check RIFF header */ @@ -383,7 +386,7 @@ static int wav_read_header(AVFormatContext *s) /* seek to next tag unless we know that we'll run into EOF */ if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) || - wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) { + wav_seek_tag(wav, pb, next_tag_ofs, SEEK_SET) < 0) { break; } } @@ -511,7 +514,7 @@ smv_out: if (CONFIG_W64_DEMUXER && wav->w64) left = find_guid(s->pb, ff_w64_guid_data) - 24; else - left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); + left = find_tag(wav, s->pb, MKTAG('d', 'a', 't', 'a')); if (left < 0) { wav->audio_eof = 1; if (wav->smv_data_ofs > 0 && !wav->smv_eof) |