1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

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 ac87eaf856

Signed-off-by: Alexander Strasser <eclipse7@gmx.net>
This commit is contained in:
Alexander Strasser 2013-08-13 18:36:21 +02:00
parent dabfa80ce2
commit dc2e4c2e53

View File

@ -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)