]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/aviobuf.c
avio: add a destructor for AVIOContext
[ffmpeg] / libavformat / aviobuf.c
index 0a7c39eacdb76b7e436945d2d507dfdb1844bf38..716c42eda9c02a1be35946613f0cdc5a15d51cca 100644 (file)
@@ -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,10 +101,10 @@ 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;
+    s->min_packet_size = 0;
     s->max_packet_size = 0;
     s->update_checksum = NULL;
     s->short_seek_threshold = SHORT_SEEK_THRESHOLD;
@@ -142,6 +143,11 @@ AVIOContext *avio_alloc_context(
     return s;
 }
 
+void avio_context_free(AVIOContext **ps)
+{
+    av_freep(ps);
+}
+
 static void writeout(AVIOContext *s, const uint8_t *data, int len)
 {
     if (!s->error) {
@@ -171,15 +177,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 +235,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)
@@ -255,6 +264,8 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
         offset1 = pos + (s->buf_ptr - s->buffer);
         if (offset == 0)
             return offset1;
+        if (offset > INT64_MAX - offset1)
+            return AVERROR(EINVAL);
         offset += offset1;
     }
     if (offset < 0)
@@ -269,8 +280,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 +311,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 +319,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;
@@ -486,6 +497,11 @@ void avio_wb24(AVIOContext *s, unsigned int val)
 
 void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
 {
+    if (type == AVIO_DATA_MARKER_FLUSH_POINT) {
+        if (s->buf_ptr - s->buffer >= s->min_packet_size)
+            avio_flush(s);
+        return;
+    }
     if (!s->write_data_type)
         return;
     // If ignoring boundary points, just treat it as unknown
@@ -542,7 +558,7 @@ static void fill_buffer(AVIOContext *s)
 
     /* make buffer smaller in case it ended up large after probing */
     if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) {
-        if (dst == s->buffer) {
+        if (dst == s->buffer && s->buf_ptr != dst) {
             int ret = ffio_set_buf_size(s, s->orig_buffer_size);
             if (ret < 0)
                 av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n");
@@ -938,6 +954,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
 
     (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
     (*s)->max_packet_size = max_packet_size;
+    (*s)->min_packet_size = h->min_packet_size;
     if(h->prot) {
         (*s)->read_pause = io_read_pause;
         (*s)->read_seek  = io_read_seek;
@@ -994,7 +1011,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 +1069,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;
 }
@@ -1112,7 +1128,9 @@ int avio_close(AVIOContext *s)
     else
         av_log(s, AV_LOG_DEBUG, "Statistics: %"PRId64" bytes read, %d seeks\n", s->bytes_read, s->seek_count);
     av_opt_free(s);
-    av_free(s);
+
+    avio_context_free(&s);
+
     return ffurl_close(h);
 }
 
@@ -1345,7 +1363,9 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
     *pbuffer = d->buffer;
     size = d->size;
     av_free(d);
-    av_free(s);
+
+    avio_context_free(&s);
+
     return size - padding;
 }
 
@@ -1388,6 +1408,8 @@ int ffio_close_null_buf(AVIOContext *s)
 
     size = d->size;
     av_free(d);
-    av_free(s);
+
+    avio_context_free(&s);
+
     return size;
 }