summaryrefslogtreecommitdiff
path: root/libavformat/aviobuf.c
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2017-06-04 01:15:50 +0200
committerMarton Balint <cus@passwd.hu>2017-06-24 18:51:29 +0200
commitc14fa7a330f634738003bee731f17ff4c5717228 (patch)
treec0a48fc4bd9c2a5b8b4642c833c9f9245de1cbb4 /libavformat/aviobuf.c
parentdc81f1a2cef11538401ee1ca13b76e61838283e6 (diff)
avformat/aviobuf: fix flushing write buffers after seeking backward or forward
This patch makes aviobuf work more like traditinal file IO, which is how people think about it. For example, in the past, aviobuf only flushed buffers until the current buffer position, even if more data was written to it previously, and a backward seek was used to reposition the IO context. From now, aviobuf will keep track of the written data, so no explicit seek will be required till the end of the buffer, or till the end of file before flushing. This fixes at least one regression, fate-vsynth3-flv was broken if flush_packets option was set to false, an explicit seek was removed in 4e3cc4bdd8acedbcc703607ed0efbb64bb5c3cc4. Also from now on, if a forward seek in the write buffer were to cause a gap between the already written data and the new file position, a flush will happen. The must_flush varable is also removed, which might have caused needless flushes with multiple seeks whithin the write buffer. Since we know the amount of data written to it, we will know when to flush. Signed-off-by: Marton Balint <cus@passwd.hu>
Diffstat (limited to 'libavformat/aviobuf.c')
-rw-r--r--libavformat/aviobuf.c26
1 files changed, 14 insertions, 12 deletions
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;
}