[FFmpeg-devel] [PATCH] add av_fast_malloc

Reimar Döffinger Reimar.Doeffinger
Sun Apr 12 14:38:48 CEST 2009


On Sun, Apr 12, 2009 at 02:01:03PM +0200, Michael Niedermayer wrote:
> On Sun, Apr 12, 2009 at 11:39:13AM +0200, Reimar D?ffinger wrote:
> > Hello,
> > this adds and uses where possible a function named av_fast_malloc.
> > It is very similar to av_fast_realloc and allows reusing an existing
> > buffer to reduce the number of actual, slow mallocs.
> > However it does not try to preserve the previous buffers contents
> > (particularly with large buffers this may be faster, if we need and come
> > up with a clever way to use realloc only where it is faster this can be
> > added later) and it also is easier to use since handling the error case
> > without creating a memleak is not as painful by far.
> > Simply replacing av_fast_realloc with av_fast_malloc fixes quite a few
> > memleaks...
> 
> > Index: libavcodec/motionpixels.c
> > ===================================================================
> > --- libavcodec/motionpixels.c	(revision 18467)
> > +++ libavcodec/motionpixels.c	(working copy)
> > @@ -297,7 +297,9 @@
> >      }
> >  
> >      /* le32 bitstream msb first */
> > -    mp->bswapbuf = av_fast_realloc(mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
> > +    av_fast_malloc((void **)&mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
> > +    if (!mp->bswapbuf)
> > +        AVERROR(ENOMEM);
> 
> _Every_ single use of av_fast_malloc() uses a void** cast, av_fast_realloc()
> managed it without ...

There you are, a version with 4 cases where it isn't needed.
For quite a few other files it would be simple to change the type to
void *, saving casts both here and in other places with minor additional
changes (e.g. an additional temporary pointer variable) and the code
would probably be better overall.
Of course I could also use the same "hack" as av_freep, i.e. using void *
instead of void ** in the function declaration...
-------------- next part --------------
Index: libavcodec/motionpixels.c
===================================================================
--- libavcodec/motionpixels.c	(revision 18467)
+++ libavcodec/motionpixels.c	(working copy)
@@ -297,7 +297,9 @@
     }
 
     /* le32 bitstream msb first */
-    mp->bswapbuf = av_fast_realloc(mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc((void **)&mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!mp->bswapbuf)
+        AVERROR(ENOMEM);
     mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4);
     if (buf_size & 3)
         memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3);
Index: libavcodec/mimic.c
===================================================================
--- libavcodec/mimic.c	(revision 18469)
+++ libavcodec/mimic.c	(working copy)
@@ -334,7 +334,7 @@
     prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
                   (AVPicture*) &ctx->buf_ptrs[ctx->cur_index]);
 
-    ctx->swap_buf = av_fast_realloc(ctx->swap_buf, &ctx->swap_buf_size,
+    av_fast_malloc(&ctx->swap_buf, &ctx->swap_buf_size,
                                  swap_buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
     if(!ctx->swap_buf)
         return AVERROR(ENOMEM);
Index: libavcodec/asv1.c
===================================================================
--- libavcodec/asv1.c	(revision 18467)
+++ libavcodec/asv1.c	(working copy)
@@ -408,7 +408,9 @@
     p->pict_type= FF_I_TYPE;
     p->key_frame= 1;
 
-    a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc((void **)&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!a->bitstream_buffer)
+        return AVERROR(ENOMEM);
 
     if(avctx->codec_id == CODEC_ID_ASV1)
         a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (const uint32_t*)buf, buf_size/4);
Index: libavcodec/utils.c
===================================================================
--- libavcodec/utils.c	(revision 18467)
+++ libavcodec/utils.c	(working copy)
@@ -80,6 +80,16 @@
     return ptr;
 }
 
+void av_fast_malloc(void **ptr, unsigned int *size, unsigned int min_size)
+{
+    if (min_size < *size)
+        return;
+    *size= FFMAX(17*min_size/16 + 32, min_size);
+    av_free(*ptr);
+    *ptr = av_malloc(*size);
+    if (!*ptr) *size = 0;
+}
+
 /* encoder management */
 static AVCodec *first_avcodec = NULL;
 
Index: libavcodec/h264.c
===================================================================
--- libavcodec/h264.c	(revision 18467)
+++ libavcodec/h264.c	(working copy)
@@ -1411,7 +1411,7 @@
     }
 
     bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; // use second escape buffer for inter data
-    h->rbsp_buffer[bufidx]= av_fast_realloc(h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc((void **)&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+FF_INPUT_BUFFER_PADDING_SIZE);
     dst= h->rbsp_buffer[bufidx];
 
     if (dst == NULL){
Index: libavcodec/mdec.c
===================================================================
--- libavcodec/mdec.c	(revision 18467)
+++ libavcodec/mdec.c	(working copy)
@@ -174,7 +174,9 @@
     p->pict_type= FF_I_TYPE;
     p->key_frame= 1;
 
-    a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc((void **)&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!a->bitstream_buffer)
+        return AVERROR(ENOMEM);
     for(i=0; i<buf_size; i+=2){
         a->bitstream_buffer[i]  = buf[i+1];
         a->bitstream_buffer[i+1]= buf[i  ];
Index: libavcodec/h263dec.c
===================================================================
--- libavcodec/h263dec.c	(revision 18467)
+++ libavcodec/h263dec.c	(working copy)
@@ -687,10 +687,12 @@
         }
 
         if(startcode_found){
-            s->bitstream_buffer= av_fast_realloc(
-                s->bitstream_buffer,
+            av_fast_malloc(
+                (void **)&s->bitstream_buffer,
                 &s->allocated_bitstream_buffer_size,
                 buf_size - current_pos + FF_INPUT_BUFFER_PADDING_SIZE);
+            if (!s->bitstream_buffer)
+                return AVERROR(ENOMEM);
             memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
             s->bitstream_buffer_size= buf_size - current_pos;
         }
Index: libavcodec/eatqi.c
===================================================================
--- libavcodec/eatqi.c	(revision 18469)
+++ libavcodec/eatqi.c	(working copy)
@@ -126,7 +126,7 @@
         return -1;
     }
 
-    t->bitstream_buf = av_fast_realloc(t->bitstream_buf, &t->bitstream_buf_size, (buf_end-buf) + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc(&t->bitstream_buf, &t->bitstream_buf_size, (buf_end-buf) + FF_INPUT_BUFFER_PADDING_SIZE);
     if (!t->bitstream_buf)
         return AVERROR(ENOMEM);
     s->dsp.bswap_buf(t->bitstream_buf, (const uint32_t*)buf, (buf_end-buf)/4);
Index: libavcodec/4xm.c
===================================================================
--- libavcodec/4xm.c	(revision 18469)
+++ libavcodec/4xm.c	(working copy)
@@ -378,7 +378,9 @@
         return -1;
     }
 
-    f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!f->bitstream_buffer)
+        return AVERROR(ENOMEM);
     f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)(buf + extra), bitstream_size/4);
     init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size);
 
@@ -656,7 +658,9 @@
 
     prestream_size= length + buf - prestream;
 
-    f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, prestream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, prestream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!f->bitstream_buffer)
+        return AVERROR(ENOMEM);
     f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)prestream, prestream_size/4);
     init_get_bits(&f->pre_gb, f->bitstream_buffer, 8*prestream_size);
 
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 18467)
+++ libavcodec/avcodec.h	(working copy)
@@ -3541,6 +3549,20 @@
 void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size);
 
 /**
+ * Allocates a buffer, reusing the given one if large enough.
+ *
+ * Contrary to av_fast_realloc the current buffer contents might not be
+ * preserved and on error the old buffer is freed, thus no special
+ * handling to avoid memleaks is necessary.
+ *
+ * @param ptr pointer to pointer to already allocated buffer, overwritten with pointer to new buffer
+ * @param size size of the buffer *ptr points to
+ * @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and
+ *                 *size 0 if an error occurred.
+ */
+void av_fast_malloc(void **ptr, unsigned int *size, unsigned int min_size);
+
+/**
  * Copy image 'src' to 'dst'.
  */
 void av_picture_copy(AVPicture *dst, const AVPicture *src,
Index: libavcodec/huffyuv.c
===================================================================
--- libavcodec/huffyuv.c	(revision 18467)
+++ libavcodec/huffyuv.c	(working copy)
@@ -956,7 +956,9 @@
 
     AVFrame *picture = data;
 
-    s->bitstream_buffer= av_fast_realloc(s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc((void **)&s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!s->bitstream_buffer)
+        return AVERROR(ENOMEM);
 
     s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, (const uint32_t*)buf, buf_size/4);
 



More information about the ffmpeg-devel mailing list