diff options
author | Tomas Härdin <tomas.hardin@codemill.se> | 2010-04-08 13:02:27 +0400 |
---|---|---|
committer | Tomas Härdin <tomas.hardin@codemill.se> | 2010-04-08 13:02:27 +0400 |
commit | 01d91b9be978753803fa6f5e73b17ab9f03a5c7b (patch) | |
tree | 35a484f2b8a8da202fdf2c815f41f8f9d14053d7 /libavformat | |
parent | ba659bedb806cb4a1dd375f723a2b0017d6afb33 (diff) |
Reusing the probe buffer to rewind the ByteIOContext in ff_probe_input_buffer() instead of seeking back to the start of the file. Once exhausted, the size of the buffer is reduced.
Originally committed as revision 22821 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/avio.h | 15 | ||||
-rw-r--r-- | libavformat/aviobuf.c | 45 | ||||
-rw-r--r-- | libavformat/utils.c | 13 |
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, |