[FFmpeg-devel] [PATCH] lavf/wavdec: Fix seeking in files with unaligned offsets

Alexander Strasser eclipse7 at gmx.net
Tue Aug 13 19:10:56 CEST 2013


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)
-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130813/1fb7ab58/attachment.asc>


More information about the ffmpeg-devel mailing list