]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/aviobuf.c
replaygain: fix gain sign decoding
[ffmpeg] / libavformat / aviobuf.c
index 15d132de29a742cef7a04fe3de41f110f7a3a1bd..0024f9e8b22e093190c5fdb79d4995f8bedc7b1d 100644 (file)
@@ -76,27 +76,31 @@ int ffio_init_context(AVIOContext *s,
                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
 {
-    s->buffer = buffer;
+    s->buffer      = buffer;
     s->buffer_size = buffer_size;
-    s->buf_ptr = buffer;
-    s->opaque = opaque;
+    s->buf_ptr     = buffer;
+    s->opaque      = opaque;
+
     url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
-    s->write_packet = write_packet;
-    s->read_packet = read_packet;
-    s->seek = seek;
-    s->pos = 0;
-    s->must_flush = 0;
-    s->eof_reached = 0;
-    s->error = 0;
-    s->seekable = AVIO_SEEKABLE_NORMAL;
+
+    s->write_packet    = write_packet;
+    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->max_packet_size = 0;
-    s->update_checksum= NULL;
-    if(!read_packet && !write_flag){
-        s->pos = buffer_size;
+    s->update_checksum = NULL;
+
+    if (!read_packet && !write_flag) {
+        s->pos     = buffer_size;
         s->buf_end = s->buffer + buffer_size;
     }
     s->read_pause = NULL;
     s->read_seek  = NULL;
+
     return 0;
 }
 
@@ -120,15 +124,17 @@ AVIOContext *avio_alloc_context(
 static void flush_buffer(AVIOContext *s)
 {
     if (s->buf_ptr > s->buffer) {
-        if (s->write_packet && !s->error){
-            int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
-            if(ret < 0){
+        if (s->write_packet && !s->error) {
+            int ret = s->write_packet(s->opaque, s->buffer,
+                                      s->buf_ptr - s->buffer);
+            if (ret < 0) {
                 s->error = ret;
             }
         }
-        if(s->update_checksum){
-            s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
-            s->checksum_ptr= s->buffer;
+        if (s->update_checksum) {
+            s->checksum     = s->update_checksum(s->checksum, s->checksum_ptr,
+                                                 s->buf_ptr - s->checksum_ptr);
+            s->checksum_ptr = s->buffer;
         }
         s->pos += s->buf_ptr - s->buffer;
     }
@@ -236,13 +242,13 @@ int64_t avio_size(AVIOContext *s)
 {
     int64_t size;
 
-    if(!s)
+    if (!s)
         return AVERROR(EINVAL);
 
     if (!s->seek)
         return AVERROR(ENOSYS);
     size = s->seek(s->opaque, 0, AVSEEK_SIZE);
-    if(size<0){
+    if (size < 0) {
         if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
             return size;
         size++;
@@ -288,29 +294,31 @@ int avio_put_str16le(AVIOContext *s, const char *str)
         uint16_t tmp;
 
         GET_UTF8(ch, *q++, break;)
-        PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;)
+        PUT_UTF16(ch, tmp, avio_wl16(s, tmp); ret += 2;)
     }
     avio_wl16(s, 0);
     ret += 2;
     return ret;
 }
 
-int ff_get_v_length(uint64_t val){
-    int i=1;
+int ff_get_v_length(uint64_t val)
+{
+    int i = 1;
 
-    while(val>>=7)
+    while (val >>= 7)
         i++;
 
     return i;
 }
 
-void ff_put_v(AVIOContext *bc, uint64_t val){
-    int i= ff_get_v_length(val);
+void ff_put_v(AVIOContext *bc, uint64_t val)
+{
+    int i = ff_get_v_length(val);
 
-    while(--i>0)
-        avio_w8(bc, 128 | (val>>(7*i)));
+    while (--i > 0)
+        avio_w8(bc, 128 | (val >> (7 * i)));
 
-    avio_w8(bc, val&127);
+    avio_w8(bc, val & 127);
 }
 
 void avio_wl64(AVIOContext *s, uint64_t val)
@@ -353,11 +361,14 @@ void avio_wb24(AVIOContext *s, unsigned int val)
 
 static void fill_buffer(AVIOContext *s)
 {
-    uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : 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;
+    uint8_t *dst        = !s->max_packet_size &&
+                          s->buf_end - s->buffer < s->buffer_size ?
+                          s->buf_end : 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;
 
-    /* can't fill the buffer without read_packet, just set EOF if appropiate */
+    /* can't fill the buffer without read_packet, just set EOF if appropriate */
     if (!s->read_packet && s->buf_ptr >= s->buf_end)
         s->eof_reached = 1;
 
@@ -365,10 +376,11 @@ static void fill_buffer(AVIOContext *s)
     if (s->eof_reached)
         return;
 
-    if(s->update_checksum && dst == s->buffer){
-        if(s->buf_end > s->checksum_ptr)
-            s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
-        s->checksum_ptr= s->buffer;
+    if (s->update_checksum && dst == s->buffer) {
+        if (s->buf_end > s->checksum_ptr)
+            s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
+                                             s->buf_end - s->checksum_ptr);
+        s->checksum_ptr = s->buffer;
     }
 
     /* make buffer smaller in case it ended up large after probing */
@@ -379,7 +391,7 @@ static void fill_buffer(AVIOContext *s)
         len = s->buffer_size;
     }
 
-    if(s->read_packet)
+    if (s->read_packet)
         len = s->read_packet(s->opaque, dst, len);
     else
         len = 0;
@@ -387,8 +399,8 @@ static void fill_buffer(AVIOContext *s)
         /* do not modify buffer if EOF reached so that a seek back can
            be done without rereading data */
         s->eof_reached = 1;
-        if(len<0)
-            s->error= len;
+        if (len < 0)
+            s->error = len;
     } else {
         s->pos += len;
         s->buf_ptr = dst;
@@ -404,8 +416,9 @@ unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
 
 unsigned long ffio_get_checksum(AVIOContext *s)
 {
-    s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
-    s->update_checksum= NULL;
+    s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
+                                     s->buf_ptr - s->checksum_ptr);
+    s->update_checksum = NULL;
     return s->checksum;
 }
 
@@ -413,10 +426,10 @@ void ffio_init_checksum(AVIOContext *s,
                    unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
                    unsigned long checksum)
 {
-    s->update_checksum= update_checksum;
-    if(s->update_checksum){
-        s->checksum= checksum;
-        s->checksum_ptr= s->buf_ptr;
+    s->update_checksum = update_checksum;
+    if (s->update_checksum) {
+        s->checksum     = checksum;
+        s->checksum_ptr = s->buf_ptr;
     }
 }
 
@@ -439,7 +452,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
         len = s->buf_end - s->buf_ptr;
         if (len > size)
             len = size;
-        if (len == 0) {
+        if (len == 0 || s->write_flag) {
             if(size > s->buffer_size && !s->update_checksum){
                 if(s->read_packet)
                     len = s->read_packet(s->opaque, buf, size);
@@ -457,7 +470,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
                     s->buf_ptr = s->buffer;
                     s->buf_end = s->buffer/* + len*/;
                 }
-            }else{
+            } else {
                 fill_buffer(s);
                 len = s->buf_end - s->buf_ptr;
                 if (len == 0)
@@ -477,15 +490,41 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
     return size1 - size;
 }
 
+int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data)
+{
+    if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
+        *data = s->buf_ptr;
+        s->buf_ptr += size;
+        return size;
+    } else {
+        *data = buf;
+        return avio_read(s, buf, size);
+    }
+}
+
 int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
 {
     int len;
 
-    if(size<0)
+    if (size < 0)
         return -1;
 
+    if (s->read_packet && s->write_flag) {
+        len = s->read_packet(s->opaque, buf, size);
+        if (len > 0)
+            s->pos += len;
+        return len;
+    }
+
     len = s->buf_end - s->buf_ptr;
     if (len == 0) {
+        /* Reset the buf_end pointer to the start of the buffer, to make sure
+         * the fill_buffer call tries to read as much data as fits into the
+         * full buffer, instead of just what space is left after buf_end.
+         * This avoids returning partial packets at the end of the buffer,
+         * for packet based inputs.
+         */
+        s->buf_end = s->buf_ptr = s->buffer;
         fill_buffer(s);
         len = s->buf_end - s->buf_ptr;
     }
@@ -801,7 +840,7 @@ int64_t avio_seek_time(AVIOContext *s, int stream_index,
     if (!s->read_seek)
         return AVERROR(ENOSYS);
     ret = s->read_seek(h, stream_index, timestamp, flags);
-    if(ret >= 0) {
+    if (ret >= 0) {
         int64_t pos;
         s->buf_ptr = s->buf_end; // Flush buffer
         pos = s->seek(h, 0, SEEK_CUR);
@@ -830,7 +869,7 @@ static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
     /* reallocate buffer if needed */
     new_size = d->pos + buf_size;
     new_allocated_size = d->allocated_size;
-    if(new_size < d->pos || new_size > INT_MAX/2)
+    if (new_size < d->pos || new_size > INT_MAX/2)
         return -1;
     while (new_size > new_allocated_size) {
         if (!new_allocated_size)
@@ -840,9 +879,12 @@ static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
     }
 
     if (new_allocated_size > d->allocated_size) {
-        d->buffer = av_realloc(d->buffer, new_allocated_size);
-        if(d->buffer == NULL)
-             return AVERROR(ENOMEM);
+        int err;
+        if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) {
+            d->allocated_size = 0;
+            d->size = 0;
+            return err;
+        }
         d->allocated_size = new_allocated_size;
     }
     memcpy(d->buffer + d->pos, buf, buf_size);
@@ -859,8 +901,8 @@ static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
 
     /* packetized write: output the header */
     AV_WB32(buf1, buf_size);
-    ret= dyn_buf_write(opaque, buf1, 4);
-    if(ret < 0)
+    ret = dyn_buf_write(opaque, buf1, 4);
+    if (ret < 0)
         return ret;
 
     /* then the data */
@@ -886,7 +928,7 @@ static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
     DynBuffer *d;
     unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
 
-    if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
+    if (sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
         return -1;
     d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
     if (!d)
@@ -922,6 +964,11 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
     static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
     int padding = 0;
 
+    if (!s) {
+        *pbuffer = NULL;
+        return 0;
+    }
+
     /* don't attempt to pad fixed-size packet buffers */
     if (!s->max_packet_size) {
         avio_write(s, padbuf, sizeof(padbuf));
@@ -936,3 +983,36 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
     av_free(s);
     return size - padding;
 }
+
+static int null_buf_write(void *opaque, uint8_t *buf, int buf_size)
+{
+    DynBuffer *d = opaque;
+
+    d->pos += buf_size;
+    if (d->pos > d->size)
+        d->size = d->pos;
+    return buf_size;
+}
+
+int ffio_open_null_buf(AVIOContext **s)
+{
+    int ret = url_open_dyn_buf_internal(s, 0);
+    if (ret >= 0) {
+        AVIOContext *pb = *s;
+        pb->write_packet = null_buf_write;
+    }
+    return ret;
+}
+
+int ffio_close_null_buf(AVIOContext *s)
+{
+    DynBuffer *d = s->opaque;
+    int size;
+
+    avio_flush(s);
+
+    size = d->size;
+    av_free(d);
+    av_free(s);
+    return size;
+}