[FFmpeg-devel] [PATCH] lavf/wavdec: Fix seeking in files with unaligned offsets
Matthieu Bouron
matthieu.bouron at gmail.com
Wed Aug 14 11:51:50 CEST 2013
On Tue, Aug 13, 2013 at 6:10 PM, Alexander Strasser <eclipse7 at gmx.net>wrote:
> 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 at gmx.net>
> ---
>
> Please comment or tell me if you have better ideas.
>
> The commit causing the regression fixed some other
> (wrongly coded?) files I think.
>
> The bug was reported (including a sample) here:
>
> http://thread.gmane.org/gmane.comp.video.ffmpeg.user/47235
>
> libavformat/wavdec.c | 17 ++++++++++-------
> 1 file 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)
>
LGTM.
Adding a fate test for this could be a good idea.
Are there a lot of samples like this ?
Matthieu
More information about the ffmpeg-devel
mailing list