summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/avio.h15
-rw-r--r--libavformat/aviobuf.c45
-rw-r--r--libavformat/utils.c13
3 files changed, 65 insertions, 8 deletions
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 649de15ea9..d186876051 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -433,6 +433,21 @@ 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.
* @note When the resource indicated by url has been opened in
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 37a6f6dee3..43e62daff6 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -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;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 5f9feec500..aa779ed80d 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -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,