[FFmpeg-devel,1/3] avformat/aviobuf: fix flushing buffers after seeking backwards

Submitted by Marton Balint on June 4, 2017, 1:35 p.m.

Details

Message ID 20170604133507.20614-1-cus@passwd.hu
State New
Headers show

Commit Message

Marton Balint June 4, 2017, 1:35 p.m.
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 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.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 libavformat/avio.h    | 33 ++++++++++++++++++---------------
 libavformat/aviobuf.c | 19 +++++++++++++------
 libavformat/version.h |  4 ++--
 3 files changed, 33 insertions(+), 23 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/avio.h b/libavformat/avio.h
index 525eb7129e..99709d5180 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,22 @@  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 / / |              |
+     *                             |/ / / / / / / / / / / /|              |
+     *                             +-----------------------+--------------+
      *
-     *                                         pos
-     *               +--------------------------+-----------------------------------+
-     *  output file: |                          |                                   |
-     *               +--------------------------+-----------------------------------+
+     *                            pos
+     *               +-------------+----------------------------------------------+
+     *  output file: |             |                                              |
+     *               +-------------+----------------------------------------------+
      *
      */
     unsigned char *buffer;  /**< Start of the buffer. */
@@ -329,6 +331,7 @@  typedef struct AVIOContext {
     int (*short_seek_get)(void *opaque);
 
     int64_t written;
+    unsigned char *buf_ptr_max; /**< Maximum reached position in the write buffer, used for flushing already written data */
 } AVIOContext;
 
 /**
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 1667e9f08b..7d1b385253 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;
 
@@ -171,15 +172,15 @@  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);
+    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;
 }
@@ -188,6 +189,7 @@  void avio_w8(AVIOContext *s, int b)
 {
     av_assert2(b>=-128 && b<=255);
     *s->buf_ptr++ = b;
+    s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max);
     if (s->buf_ptr >= s->buf_end)
         flush_buffer(s);
 }
@@ -198,6 +200,7 @@  void ffio_fill(AVIOContext *s, int b, int count)
         int len = FFMIN(s->buf_end - s->buf_ptr, count);
         memset(s->buf_ptr, b, len);
         s->buf_ptr += len;
+        s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max);
 
         if (s->buf_ptr >= s->buf_end)
             flush_buffer(s);
@@ -217,6 +220,7 @@  void avio_write(AVIOContext *s, const unsigned char *buf, int size)
         int len = FFMIN(s->buf_end - s->buf_ptr, size);
         memcpy(s->buf_ptr, buf, len);
         s->buf_ptr += len;
+        s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max);
 
         if (s->buf_ptr >= s->buf_end)
             flush_buffer(s);
@@ -228,8 +232,11 @@  void avio_write(AVIOContext *s, const unsigned char *buf, int size)
 
 void avio_flush(AVIOContext *s)
 {
+    int seekback = s->write_flag ? 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)
@@ -308,7 +315,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 +1001,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;
 }
diff --git a/libavformat/version.h b/libavformat/version.h
index 411fd6613d..b00a8b0333 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,8 +32,8 @@ 
 // 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  72
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MINOR  73
+#define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \