[FFmpeg-devel] [PATCH] frame: add an av_frame_new_side_data_from_buf function
James Almer
jamrial at gmail.com
Thu Mar 1 19:01:21 EET 2018
On 3/1/2018 1:48 PM, Rostislav Pehlivanov wrote:
> Signed-off-by: Rostislav Pehlivanov <atomnuker at gmail.com>
> ---
>
> Changed so that the function will not create a new reference.
>
> libavutil/frame.c | 45 +++++++++++++++++++++++++--------------------
> libavutil/frame.h | 17 +++++++++++++++++
> 2 files changed, 42 insertions(+), 20 deletions(-)
>
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index 662a7e5ab5..a49c853493 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -26,11 +26,6 @@
> #include "mem.h"
> #include "samplefmt.h"
>
> -
> -static AVFrameSideData *frame_new_side_data(AVFrame *frame,
> - enum AVFrameSideDataType type,
> - AVBufferRef *buf);
> -
> #if FF_API_FRAME_GET_SET
> MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp)
> MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration)
> @@ -356,8 +351,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
> }
> memcpy(sd_dst->data, sd_src->data, sd_src->size);
> } else {
> - sd_dst = frame_new_side_data(dst, sd_src->type, av_buffer_ref(sd_src->buf));
> + AVBufferRef *ref = av_buffer_ref(sd_src->buf);
> + sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
> if (!sd_dst) {
> + av_buffer_unref(&ref);
> wipe_side_data(dst);
> return AVERROR(ENOMEM);
> }
> @@ -642,9 +639,9 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
> return NULL;
> }
>
> -static AVFrameSideData *frame_new_side_data(AVFrame *frame,
> - enum AVFrameSideDataType type,
> - AVBufferRef *buf)
> +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
> + enum AVFrameSideDataType type,
> + AVBufferRef *buf)
> {
> AVFrameSideData *ret, **tmp;
>
> @@ -652,18 +649,20 @@ static AVFrameSideData *frame_new_side_data(AVFrame *frame,
> return NULL;
>
> if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
> - goto fail;
> + return NULL;
> +
> + ret = av_mallocz(sizeof(*ret));
> + if (!ret)
> + return NULL;
>
> tmp = av_realloc(frame->side_data,
> (frame->nb_side_data + 1) * sizeof(*frame->side_data));
> - if (!tmp)
> - goto fail;
> + if (!tmp) {
> + av_free(tmp);
> + return NULL;
> + }
> frame->side_data = tmp;
>
> - ret = av_mallocz(sizeof(*ret));
> - if (!ret)
> - goto fail;
> -
Moving this up in the function is an unrelated change.
Also there's not a lot to win from doing it. Even if realloc succeeded
and malloc failed, the next time you try to add a new side data the
realloc would effectively be a noop as new size == current size.
> ret->buf = buf;
> ret->data = ret->buf->data;
> ret->size = buf->size;
> @@ -672,17 +671,23 @@ static AVFrameSideData *frame_new_side_data(AVFrame *frame,
> frame->side_data[frame->nb_side_data++] = ret;
>
> return ret;
> -fail:
> - av_buffer_unref(&buf);
> - return NULL;
> }
>
> AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
> enum AVFrameSideDataType type,
> int size)
> {
> + AVFrameSideData *ret;
> + AVBufferRef *buf = av_buffer_alloc(size);
> + if (!buf)
> + return NULL;
>
> - return frame_new_side_data(frame, type, av_buffer_alloc(size));
> + ret = av_frame_new_side_data_from_buf(frame, type, buf);
> + if (!ret) {
> + av_buffer_unref(&buf);
> + return NULL;
> + }
> + return ret;
if (!ret)
av_buffer_unref(&buf);
return ret;
> }
>
> AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index d54bd9a354..6745e7d7b2 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -800,6 +800,23 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
> enum AVFrameSideDataType type,
> int size);
>
> +/**
> + * Add a new side data to a frame from an existing AVBufferRef
> + *
> + * The ownership is not changed, its up to users to create and pass a
> + * new reference if they still need the AVBufferRef.
This is confusing. The ownership of whatever buffer ref you pass *does*
change on success.
> + * On error, nothing will be changed and the function will return NULL.
> + *
> + * @param frame a frame to which the side data should be added
> + * @param type type of the added side data
> + * @param buf the AVBufferRef to add as side data
> + *
> + * @return newly added side data on success, NULL on error
Try instead something like.
/**
* Add a new side data to a frame from an existing AVBufferRef
*
* @param frame a frame to which the side data should be added
* @param type type of the added side data
* @param buf the AVBufferRef to add as side data. The ownership of the
* reference is transferred to the frame.
*
* @return newly added side data on success, NULL on error. On failure
* the frame is unchanged and the AVBufferRef remains owned by
* the caller.
*/
> + */
> +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
> + enum AVFrameSideDataType type,
> + AVBufferRef *buf);
> +
> /**
> * @return a pointer to the side data of a given type on success, NULL if there
> * is no side data with such type in this frame.
>
More information about the ffmpeg-devel
mailing list