Reusing the probe buffer to rewind the ByteIOContext in ff_probe_input_buffer() inste...
authorTomas Härdin <tomas.hardin@codemill.se>
Thu, 8 Apr 2010 09:02:27 +0000 (09:02 +0000)
committerTomas Härdin <tomas.hardin@codemill.se>
Thu, 8 Apr 2010 09:02:27 +0000 (09:02 +0000)
Originally committed as revision 22821 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/avio.h
libavformat/aviobuf.c
libavformat/utils.c

index 649de15..d186876 100644 (file)
@@ -432,6 +432,21 @@ int url_setbufsize(ByteIOContext *s, int buf_size);
 int url_resetbuf(ByteIOContext *s, int flags);
 #endif
 
+/**
+ * Rewinds the ByteIOContext using the specified buffer containing the first buf_size bytes of the file.
+ * Used after probing to avoid seeking.
+ * Joins buf and s->buffer, taking any overlap into consideration.
+ * @note s->buffer must overlap with buf or they can't be joined and the function fails
+ * @note This function is NOT part of the public API
+ *
+ * @param s The read-only ByteIOContext to rewind
+ * @param buf The probe buffer containing the first buf_size bytes of the file
+ * @param buf_size The size of buf
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ */
+int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size);
+
 /**
  * Creates and initializes a ByteIOContext for accessing the
  * resource indicated by url.
index 37a6f6d..43e62da 100644 (file)
@@ -295,6 +295,7 @@ static void fill_buffer(ByteIOContext *s)
 {
     uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_ptr : s->buffer;
     int len= s->buffer_size - (dst - s->buffer);
+    int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
 
     assert(s->buf_ptr == s->buf_end);
 
@@ -308,6 +309,14 @@ static void fill_buffer(ByteIOContext *s)
         s->checksum_ptr= s->buffer;
     }
 
+    /* make buffer smaller in case it ended up large after probing */
+    if (s->buffer_size > max_buffer_size) {
+        url_setbufsize(s, max_buffer_size);
+
+        s->checksum_ptr = dst = s->buffer;
+        len = s->buffer_size;
+    }
+
     if(s->read_packet)
         len = s->read_packet(s->opaque, dst, len);
     else
@@ -611,6 +620,42 @@ static int url_resetbuf(ByteIOContext *s, int flags)
     return 0;
 }
 
+int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size)
+{
+    int64_t buffer_start;
+    int buffer_size;
+    int overlap, new_size;
+
+    if (s->write_flag)
+        return AVERROR(EINVAL);
+
+    buffer_size = s->buf_end - s->buffer;
+
+    /* the buffers must touch or overlap */
+    if ((buffer_start = s->pos - buffer_size) > buf_size)
+        return AVERROR(EINVAL);
+
+    overlap = buf_size - buffer_start;
+    new_size = buf_size + buffer_size - overlap;
+
+    if (new_size > buf_size) {
+        if (!(buf = av_realloc(buf, new_size)))
+            return AVERROR(ENOMEM);
+
+        memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
+        buf_size = new_size;
+    }
+
+    av_free(s->buffer);
+    s->buf_ptr = s->buffer = buf;
+    s->pos = s->buffer_size = buf_size;
+    s->buf_end = s->buf_ptr + buf_size;
+    s->eof_reached = 0;
+    s->must_flush = 0;
+
+    return 0;
+}
+
 int url_fopen(ByteIOContext **s, const char *filename, int flags)
 {
     URLContext *h;
index 5f9feec..aa779ed 100644 (file)
@@ -516,19 +516,16 @@ int ff_probe_input_buffer(ByteIOContext **pb, AVInputFormat **fmt,
         }
     }
 
-    av_free(buf);
-
     if (!*fmt) {
+        av_free(buf);
         return AVERROR_INVALIDDATA;
     }
 
-    if (url_fseek(*pb, 0, SEEK_SET) < 0) {
-        url_fclose(*pb);
-        if (url_fopen(pb, filename, URL_RDONLY) < 0)
-            return AVERROR(EIO);
-    }
+    /* rewind. reuse probe buffer to avoid seeking */
+    if ((ret = ff_rewind_with_probe_data(*pb, buf, pd.buf_size)) < 0)
+        av_free(buf);
 
-    return 0;
+    return ret;
 }
 
 int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,