]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/aviobuf.c
Move AVStream->codec_info_nb_frames increment after try_decode_frame
[ffmpeg] / libavformat / aviobuf.c
index da05251279a681fb5942354537902dafe10a343f..df4ea60227f6f6fa301264b7d3d37997b73ab4aa 100644 (file)
@@ -130,6 +130,8 @@ int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence)
 {
     int64_t offset1;
     int64_t pos;
+    int force = whence & AVSEEK_FORCE;
+    whence &= ~AVSEEK_FORCE;
 
     if(!s)
         return AVERROR(EINVAL);
@@ -151,15 +153,14 @@ int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence)
         /* can do the seek inside the buffer */
         s->buf_ptr = s->buffer + offset1;
     } else if(s->is_streamed && !s->write_flag && offset1 >= 0 &&
-              (   offset1 < (s->buf_end - s->buffer) + (1<<16)
-               || (whence & AVSEEK_FORCE))){
+              (whence != SEEK_END || force)) {
         while(s->pos < offset && !s->eof_reached)
             fill_buffer(s);
         if (s->eof_reached)
             return AVERROR_EOF;
         s->buf_ptr = s->buf_end + offset - s->pos;
     } else {
-        int64_t res = AVERROR(EPIPE);
+        int64_t res;
 
 #if CONFIG_MUXERS || CONFIG_NETWORK
         if (s->write_flag) {
@@ -167,7 +168,9 @@ int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence)
             s->must_flush = 1;
         }
 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */
-        if (!s->seek || (res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
+        if (!s->seek)
+            return AVERROR(EPIPE);
+        if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
             return res;
         if (!s->write_flag)
             s->buf_end = s->buffer;
@@ -196,7 +199,7 @@ int64_t url_fsize(ByteIOContext *s)
         return AVERROR(EINVAL);
 
     if (!s->seek)
-        return AVERROR(EPIPE);
+        return AVERROR(ENOSYS);
     size = s->seek(s->opaque, 0, AVSEEK_SIZE);
     if(size<0){
         if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
@@ -294,6 +297,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);
 
@@ -307,6 +311,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
@@ -610,6 +622,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;
@@ -697,8 +745,13 @@ int64_t av_url_read_fseek(ByteIOContext *s, int stream_index,
         return AVERROR(ENOSYS);
     ret = s->read_seek(h, stream_index, timestamp, flags);
     if(ret >= 0) {
+        int64_t pos;
         s->buf_ptr = s->buf_end; // Flush buffer
-        s->pos = s->seek(h, 0, SEEK_CUR);
+        pos = s->seek(h, 0, SEEK_CUR);
+        if (pos >= 0)
+            s->pos = pos;
+        else if (pos != AVERROR(ENOSYS))
+            ret = pos;
     }
     return ret;
 }
@@ -841,6 +894,14 @@ int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
 {
     DynBuffer *d = s->opaque;
     int size;
+    static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
+    int padding = 0;
+
+    /* don't attempt to pad fixed-size packet buffers */
+    if (!s->max_packet_size) {
+        put_buffer(s, padbuf, sizeof(padbuf));
+        padding = FF_INPUT_BUFFER_PADDING_SIZE;
+    }
 
     put_flush_packet(s);
 
@@ -848,6 +909,6 @@ int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
     size = d->size;
     av_free(d);
     av_free(s);
-    return size;
+    return size - padding;
 }
 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */