[FFmpeg-cvslog] wav: keep parsing until EOF if the input is seekable and we know the size of the data tag

Tomas Härdin git at videolan.org
Thu Jul 14 02:36:46 CEST 2011


ffmpeg | branch: master | Tomas Härdin <tomas.hardin at codemill.se> | Wed May 18 13:48:02 2011 +0200| [67b1761fcbd8ddcfe7bdb47ace5f46435d8313fa] | committer: Anton Khirnov

wav: keep parsing until EOF if the input is seekable and we know the size of the data tag

Signed-off-by: Anton Khirnov <anton at khirnov.net>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=67b1761fcbd8ddcfe7bdb47ace5f46435d8313fa
---

 libavformat/wav.c |   47 ++++++++++++++++++++++++++++++++---------------
 1 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/libavformat/wav.c b/libavformat/wav.c
index cf815ef..a8312e2 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -296,7 +296,7 @@ static int wav_read_header(AVFormatContext *s,
     AVStream *st;
     WAVContext *wav = s->priv_data;
     int ret, got_fmt = 0;
-    int64_t next_tag_ofs;
+    int64_t next_tag_ofs, data_ofs = -1;
 
     /* check RIFF header */
     tag = avio_rl32(pb);
@@ -327,13 +327,13 @@ static int wav_read_header(AVFormatContext *s,
         avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
     }
 
-
     for (;;) {
-        if (pb->eof_reached)
-            return -1;
         size = next_tag(pb, &tag);
         next_tag_ofs = avio_tell(pb) + size;
 
+        if (pb->eof_reached)
+            break;
+
         switch (tag) {
         case MKTAG('f', 'm', 't', ' '):
             /* only parse the first 'fmt ' tag found */
@@ -350,26 +350,43 @@ static int wav_read_header(AVFormatContext *s,
                 return AVERROR_INVALIDDATA;
             }
 
-            goto break_loop;
+            if (rf64) {
+                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
+            } else {
+                data_size = size;
+                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
+            }
+
+            data_ofs = avio_tell(pb);
+
+            /* don't look for footer metadata if we can't seek or if we don't
+             * know where the data tag ends
+             */
+            if (!pb->seekable || (!rf64 && !size))
+                goto break_loop;
+            break;
         case MKTAG('f','a','c','t'):
             if (!sample_count)
                 sample_count = avio_rl32(pb);
             break;
         }
-        avio_seek(pb, next_tag_ofs, SEEK_SET);
+
+        /* seek to next tag unless we know that we'll run into EOF */
+        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
+            avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) {
+            break;
+        }
     }
 break_loop:
-    if (rf64)
-        size = data_size;
-    if (size < 0)
-        return -1;
-    if (!size) {
-        wav->data_end = INT64_MAX;
-    } else
-        wav->data_end= avio_tell(pb) + size;
+    if (data_ofs < 0) {
+        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    avio_seek(pb, data_ofs, SEEK_SET);
 
     if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
-        sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
+        sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
     if (sample_count)
         st->duration = sample_count;
     return 0;



More information about the ffmpeg-cvslog mailing list