[FFmpeg-devel] [PATCH 2/2] avutil: make AVFrameSideData buffers ref-counted.

Ronald S. Bultje rsbultje at gmail.com
Mon Mar 23 17:36:03 CET 2015


Hi,

On Mon, Mar 23, 2015 at 12:16 PM, wm4 <nfxjfg at googlemail.com> wrote:

> On Mon, 23 Mar 2015 11:11:19 -0400
> "Ronald S. Bultje" <rsbultje at gmail.com> wrote:
>
> > ---
> >  libavutil/frame.c | 53
> ++++++++++++++++++++++++++++++++++++++---------------
> >  libavutil/frame.h |  1 +
> >  2 files changed, 39 insertions(+), 15 deletions(-)
> >
> > diff --git a/libavutil/frame.c b/libavutil/frame.c
> > index 85f5637..4596927 100644
> > --- a/libavutil/frame.c
> > +++ b/libavutil/frame.c
> > @@ -115,7 +115,7 @@ static void free_side_data(AVFrameSideData **ptr_sd)
> >  {
> >      AVFrameSideData *sd = *ptr_sd;
> >
> > -    av_freep(&sd->data);
> > +    av_buffer_unref(&sd->buf);
> >      av_dict_free(&sd->metadata);
> >      av_freep(ptr_sd);
> >  }
> > @@ -275,7 +275,7 @@ int av_frame_get_buffer(AVFrame *frame, int align)
> >      return AVERROR(EINVAL);
> >  }
> >
> > -int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
> > +static int frame_copy_props(AVFrame *dst, const AVFrame *src, int
> force_copy)
> >  {
> >      int i;
> >
> > @@ -320,13 +320,28 @@ int av_frame_copy_props(AVFrame *dst, const
> AVFrame *src)
> >          if (   sd_src->type == AV_FRAME_DATA_PANSCAN
> >              && (src->width != dst->width || src->height != dst->height))
> >              continue;
> > -        sd_dst = av_frame_new_side_data(dst, sd_src->type,
> > -                                        sd_src->size);
> > -        if (!sd_dst) {
> > -            wipe_side_data(dst);
> > -            return AVERROR(ENOMEM);
> > +        if (force_copy) {
> > +            sd_dst = av_frame_new_side_data(dst, sd_src->type,
> > +                                            sd_src->size);
> > +            if (!sd_dst) {
> > +                wipe_side_data(dst);
> > +                return AVERROR(ENOMEM);
> > +            }
> > +            memcpy(sd_dst->data, sd_src->data, sd_src->size);
> > +        } else {
> > +            sd_dst = av_frame_new_side_data(dst, sd_src->type, 0);
> > +            if (!sd_dst) {
> > +                wipe_side_data(dst);
> > +                return AVERROR(ENOMEM);
> > +            }
> > +            sd_dst->buf = av_buffer_ref(sd_src->buf);
> > +            if (!sd_dst->buf) {
> > +                wipe_side_data(dst);
> > +                return AVERROR(ENOMEM);
> > +            }
> > +            sd_dst->data = sd_dst->buf->data;
> > +            sd_dst->size = sd_dst->buf->size;
> >          }
> > -        memcpy(sd_dst->data, sd_src->data, sd_src->size);
> >          av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
> >      }
> >
> > @@ -356,7 +371,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
> >      dst->channel_layout = src->channel_layout;
> >      dst->nb_samples     = src->nb_samples;
> >
> > -    ret = av_frame_copy_props(dst, src);
> > +    ret = frame_copy_props(dst, src, 0);
> >      if (ret < 0)
> >          return ret;
> >
> > @@ -530,6 +545,11 @@ int av_frame_make_writable(AVFrame *frame)
> >      return 0;
> >  }
> >
> > +int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
> > +{
> > +    return frame_copy_props(dst, src, 1);
> > +}
> > +
> >  AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
> >  {
> >      uint8_t *data;
> > @@ -580,13 +600,16 @@ AVFrameSideData *av_frame_new_side_data(AVFrame
> *frame,
> >      if (!ret)
> >          return NULL;
> >
> > -    ret->data = av_malloc(size);
> > -    if (!ret->data) {
> > -        av_freep(&ret);
> > -        return NULL;
> > -    }
> > +    if (size > 0) {
> > +        ret->buf = av_buffer_alloc(size);
> > +        if (!ret->buf) {
> > +            av_freep(&ret);
> > +            return NULL;
> > +        }
> >
> > -    ret->size = size;
> > +        ret->data = ret->buf->data;
> > +        ret->size = size;
> > +    }
> >      ret->type = type;
> >
> >      frame->side_data[frame->nb_side_data++] = ret;
> > diff --git a/libavutil/frame.h b/libavutil/frame.h
> > index 6b9ac6a..e65ad79 100644
> > --- a/libavutil/frame.h
> > +++ b/libavutil/frame.h
> > @@ -129,6 +129,7 @@ typedef struct AVFrameSideData {
> >      uint8_t *data;
> >      int      size;
> >      AVDictionary *metadata;
> > +    AVBufferRef *buf;
> >  } AVFrameSideData;
> >
> >  /**
>
> What if someone wants to do write-accesses to the side-data? I don't
> think this patch handles this case.  av_frame_make_writable() should be
> extended.


av_frame_make_writable() copies (as opposed to refcounts) the side-data, so
that works fine. The refcount-increment code is only invoked for
av_frame_ref().

Ronald


More information about the ffmpeg-devel mailing list