[FFmpeg-devel] [PATCH 1/4] lavu/buffer: add a convenience function for replacing buffers

Anton Khirnov anton at khirnov.net
Mon Jun 8 14:34:47 EEST 2020


Quoting James Almer (2020-06-05 15:05:33)
> On 6/5/2020 7:02 AM, Anton Khirnov wrote:
> > A common pattern e.g. in libavcodec is replacing/updating buffer
> > references: unref old one, ref new one. This function allows simplifying
> > such code an avoiding unnecessary refs+unrefs if the references are
> > already equivalent.
> > ---
> >  doc/APIchanges     |  3 +++
> >  libavutil/buffer.c | 22 ++++++++++++++++++++++
> >  libavutil/buffer.h | 17 +++++++++++++++++
> >  3 files changed, 42 insertions(+)
> > 
> > diff --git a/doc/APIchanges b/doc/APIchanges
> > index fb5534b5f5..757d814eee 100644
> > --- a/doc/APIchanges
> > +++ b/doc/APIchanges
> > @@ -15,6 +15,9 @@ libavutil:     2017-10-21
> >  
> >  API changes, most recent first:
> >  
> > +2020-xx-xx - xxxxxxxxxx - lavc 56.50.100 - buffer.h
> > +  Add a av_buffer_replace() convenience function.
> > +
> >  2020-xx-xx - xxxxxxxxxx - lavc 58.88.100 - avcodec.h codec.h
> >    Move AVCodec-related public API to new header codec.h.
> >  
> > diff --git a/libavutil/buffer.c b/libavutil/buffer.c
> > index 6d9cb7428e..ecd83da9c3 100644
> > --- a/libavutil/buffer.c
> > +++ b/libavutil/buffer.c
> > @@ -216,6 +216,28 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size)
> >      return 0;
> >  }
> >  
> > +int av_buffer_replace(AVBufferRef **pdst, AVBufferRef *src)
> > +{
> > +    AVBufferRef *dst = *pdst;
> > +
> > +    if (!src) {
> > +        av_buffer_unref(pdst);
> > +        return !!dst;
> > +    }
> > +
> > +    if (dst && dst->buffer == src->buffer) {
> > +        /* make sure the data pointers match */
> 
> Maybe overkill, but if dst->buffer == src->buffer then you could also
> add an assert to ensure that src->buffer is not writable.

Why? That should always be true, since there are two references, but I
don't see how is that related to what the function is doing.

> 
> > +        dst->data = src->data;
> > +        dst->size = src->size;
> > +        return 0;
> > +    }
> > +
> 
> > +    av_buffer_unref(pdst);
> > +    *pdst = av_buffer_ref(src);
> > +
> > +    return *pdst ? 1 : AVERROR(ENOMEM);
> > +}
> 
> Nit: How about instead something like
> 
> newbuf = av_buffer_ref(src);
> if (!newbuf)
>     return AVERROR(ENOMEM);
> 
> buffer_replace(pdst, &newbuf);
> 
> return 0;
> 
> It's IMO cleaner looking, and prevents pdst from being modified on failure.

That requires pdst to be an existing buffer, which is not guranteed.
Also, I don't see the logic behind buffer_replace(), so it does not seem
simpler.

> 
> > +
> >  AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
> >                                     AVBufferRef* (*alloc)(void *opaque, int size),
> >                                     void (*pool_free)(void *opaque))
> > diff --git a/libavutil/buffer.h b/libavutil/buffer.h
> > index e0f94314f4..497dc98c20 100644
> > --- a/libavutil/buffer.h
> > +++ b/libavutil/buffer.h
> > @@ -197,6 +197,23 @@ int av_buffer_make_writable(AVBufferRef **buf);
> >   */
> >  int av_buffer_realloc(AVBufferRef **buf, int size);
> >  
> > +/**
> > + * Ensure dst refers to the same data as src.
> > + *
> > + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst
> > + * and replace it with a new reference to src.
> > + *
> > + * @param dst Pointer to either a valid buffer reference or NULL. On success,
> > + *            this will point to a buffer reference equivalent to src. On
> > + *            failure, dst will be unreferenced.
> > + * @param src A buffer reference to replace dst with. May be NULL, then this
> > + *            function is equivalent to av_buffer_unref(dst).
> > + * @return 0 if dst was equivalent to src on input and nothing was done
> > + *         1 if dst was replaced with a new reference to src
> 
> Either of these values mean success, and the user will not really care
> if the function was a no-op or a ref (the next three patches are an
> example of this). In the end, dst is guaranteed to point to the same
> underlying buffer as src as long as the return value is not negative,
> regardless of what the function did internally.
> 
> This is already the case for av_buffer_make_writable(), where we don't
> discriminate between a no-op and a reallocation either, and in other
> similar functions (packet, frame, etc), so I'd strongly prefer if we can
> keep this consistent.

Ok, changed locally.

-- 
Anton Khirnov


More information about the ffmpeg-devel mailing list