[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