Commit dc2e4c2e authored by Alexander Strasser's avatar Alexander Strasser

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 ac87eaf8Signed-off-by: 's avatarAlexander Strasser <eclipse7@gmx.net>
parent dabfa80c
...@@ -54,6 +54,7 @@ typedef struct WAVDemuxContext { ...@@ -54,6 +54,7 @@ typedef struct WAVDemuxContext {
int spdif; int spdif;
int smv_cur_pt; int smv_cur_pt;
int smv_given_first; int smv_given_first;
int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
} WAVDemuxContext; } WAVDemuxContext;
#if CONFIG_WAV_DEMUXER #if CONFIG_WAV_DEMUXER
...@@ -64,16 +65,16 @@ static int64_t next_tag(AVIOContext *pb, uint32_t *tag) ...@@ -64,16 +65,16 @@ static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
return avio_rl32(pb); return avio_rl32(pb);
} }
/* RIFF chunks are always on a even offset. */ /* RIFF chunks are always at even offsets relative to where they start. */
static int64_t wav_seek_tag(AVIOContext *s, int64_t offset, int whence) 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 avio_seek(s, offset, whence);
} }
/* return the size of the found tag */ /* 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; unsigned int tag;
int64_t size; int64_t size;
...@@ -84,7 +85,7 @@ static int64_t find_tag(AVIOContext *pb, uint32_t tag1) ...@@ -84,7 +85,7 @@ static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
size = next_tag(pb, &tag); size = next_tag(pb, &tag);
if (tag == tag1) if (tag == tag1)
break; break;
wav_seek_tag(pb, size, SEEK_CUR); wav_seek_tag(wav, pb, size, SEEK_CUR);
} }
return size; return size;
} }
...@@ -247,6 +248,8 @@ static int wav_read_header(AVFormatContext *s) ...@@ -247,6 +248,8 @@ static int wav_read_header(AVFormatContext *s)
int ret, got_fmt = 0; int ret, got_fmt = 0;
int64_t next_tag_ofs, data_ofs = -1; int64_t next_tag_ofs, data_ofs = -1;
wav->unaligned = avio_tell(s->pb) & 1;
wav->smv_data_ofs = -1; wav->smv_data_ofs = -1;
/* check RIFF header */ /* check RIFF header */
...@@ -383,7 +386,7 @@ static int wav_read_header(AVFormatContext *s) ...@@ -383,7 +386,7 @@ static int wav_read_header(AVFormatContext *s)
/* seek to next tag unless we know that we'll run into EOF */ /* seek to next tag unless we know that we'll run into EOF */
if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) || 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; break;
} }
} }
...@@ -511,7 +514,7 @@ smv_out: ...@@ -511,7 +514,7 @@ smv_out:
if (CONFIG_W64_DEMUXER && wav->w64) if (CONFIG_W64_DEMUXER && wav->w64)
left = find_guid(s->pb, ff_w64_guid_data) - 24; left = find_guid(s->pb, ff_w64_guid_data) - 24;
else 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) { if (left < 0) {
wav->audio_eof = 1; wav->audio_eof = 1;
if (wav->smv_data_ofs > 0 && !wav->smv_eof) if (wav->smv_data_ofs > 0 && !wav->smv_eof)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment