diff --git a/libavformat/avio.h b/libavformat/avio.h index 525eb7129e..844a5723d3 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -168,8 +168,9 @@ typedef struct AVIOContext { const AVClass *av_class; /* - * The following shows the relationship between buffer, buf_ptr, buf_end, buf_size, - * and pos, when reading and when writing (since AVIOContext is used for both): + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): * ********************************************************************************** * READING @@ -196,21 +197,24 @@ typedef struct AVIOContext { * WRITING ********************************************************************************** * - * | buffer_size | - * |-------------------------------| - * | | + * | buffer_size | + * |--------------------------------------| + * | | * - * buffer buf_ptr buf_end - * +-------------------+-----------+ - * |/ / / / / / / / / /| | - * write buffer: | / to be flushed / | | - * |/ / / / / / / / / /| | - * +-------------------+-----------+ + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek * - * pos - * +--------------------------+-----------------------------------+ - * output file: | | | - * +--------------------------+-----------------------------------+ + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ * */ unsigned char *buffer; /**< Start of the buffer. */ @@ -226,7 +230,7 @@ typedef struct AVIOContext { int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); int64_t (*seek)(void *opaque, int64_t offset, int whence); int64_t pos; /**< position in the file of the current buffer */ - int must_flush; /**< true if the next seek should flush */ + int must_flush; /**< unused */ int eof_reached; /**< true if eof reached */ int write_flag; /**< true if open for writing */ int max_packet_size; @@ -329,6 +333,12 @@ typedef struct AVIOContext { int (*short_seek_get)(void *opaque); int64_t written; + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; } AVIOContext; /** diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 1667e9f08b..dcb91570d8 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -91,6 +91,7 @@ int ffio_init_context(AVIOContext *s, s->orig_buffer_size = s->buffer_size = buffer_size; s->buf_ptr = buffer; + s->buf_ptr_max = buffer; s->opaque = opaque; s->direct = 0; @@ -100,7 +101,6 @@ int ffio_init_context(AVIOContext *s, s->read_packet = read_packet; s->seek = seek; s->pos = 0; - s->must_flush = 0; s->eof_reached = 0; s->error = 0; s->seekable = seek ? AVIO_SEEKABLE_NORMAL : 0; @@ -171,15 +171,16 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) static void flush_buffer(AVIOContext *s) { - if (s->write_flag && s->buf_ptr > s->buffer) { - writeout(s, s->buffer, s->buf_ptr - s->buffer); + s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max); + if (s->write_flag && s->buf_ptr_max > s->buffer) { + writeout(s, s->buffer, s->buf_ptr_max - s->buffer); if (s->update_checksum) { s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, - s->buf_ptr - s->checksum_ptr); + s->buf_ptr_max - s->checksum_ptr); s->checksum_ptr = s->buffer; } } - s->buf_ptr = s->buffer; + s->buf_ptr = s->buf_ptr_max = s->buffer; if (!s->write_flag) s->buf_end = s->buffer; } @@ -228,8 +229,10 @@ void avio_write(AVIOContext *s, const unsigned char *buf, int size) void avio_flush(AVIOContext *s) { + int seekback = s->write_flag ? FFMIN(0, s->buf_ptr - s->buf_ptr_max) : 0; flush_buffer(s); - s->must_flush = 0; + if (seekback) + avio_seek(s, seekback, SEEK_CUR); } int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) @@ -269,8 +272,9 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) short_seek = s->short_seek_threshold; offset1 = offset - pos; // "offset1" is the relative offset from the beginning of s->buffer - if (!s->must_flush && (!s->direct || !s->seek) && - offset1 >= 0 && offset1 <= buffer_size - s->write_flag) { + s->buf_ptr_max = FFMAX(s->buf_ptr_max, s->buf_ptr); + if ((!s->direct || !s->seek) && + offset1 >= 0 && offset1 <= (s->write_flag ? s->buf_ptr_max - s->buffer : buffer_size)) { /* can do the seek inside the buffer */ s->buf_ptr = s->buffer + offset1; } else if ((!(s->seekable & AVIO_SEEKABLE_NORMAL) || @@ -299,7 +303,6 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) int64_t res; if (s->write_flag) { flush_buffer(s); - s->must_flush = 1; } if (!s->seek) return AVERROR(EPIPE); @@ -308,7 +311,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) s->seek_count ++; if (!s->write_flag) s->buf_end = s->buffer; - s->buf_ptr = s->buffer; + s->buf_ptr = s->buf_ptr_max = s->buffer; s->pos = offset; } s->eof_reached = 0; @@ -994,7 +997,7 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size) s->buffer = buffer; s->orig_buffer_size = s->buffer_size = buf_size; - s->buf_ptr = buffer; + s->buf_ptr = s->buf_ptr_max = buffer; url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); return 0; } @@ -1052,7 +1055,6 @@ int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **bufp, int buf_si s->pos = buf_size; s->buf_end = s->buf_ptr + buf_size; s->eof_reached = 0; - s->must_flush = 0; return 0; } diff --git a/libavformat/version.h b/libavformat/version.h index b00a8b0333..1fb8ffb2b9 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 73 +#define LIBAVFORMAT_VERSION_MINOR 74 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \