Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] avutil/frame: add av_frame_replace
@ 2022-06-05 15:28 James Almer
  2022-06-05 15:42 ` Andreas Rheinhardt
  0 siblings, 1 reply; 11+ messages in thread
From: James Almer @ 2022-06-05 15:28 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
Now taking into account the new channel layout API fields, supporting non
refcouted src, plus changing the documentation to state that the dst frame
properties will be replaced by those from src even if the data described
by both frames is the same.

Still missing APIChanges entry and version bump.

 libavutil/frame.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/frame.h |  17 ++++++
 2 files changed, 161 insertions(+)

diff --git a/libavutil/frame.c b/libavutil/frame.c
index 4c16488c66..2a4a2c27ad 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -461,6 +461,150 @@ fail:
     return ret;
 }
 
+int av_frame_replace(AVFrame *dst, const AVFrame *src)
+{
+    int i, ret = 0;
+
+    dst->format         = src->format;
+    dst->width          = src->width;
+    dst->height         = src->height;
+    dst->nb_samples     = src->nb_samples;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    dst->channels       = src->channels;
+    dst->channel_layout = src->channel_layout;
+    if (!av_channel_layout_check(&src->ch_layout)) {
+        av_channel_layout_uninit(&dst->ch_layout);
+        if (src->channel_layout)
+            av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout);
+        else {
+            dst->ch_layout.nb_channels = src->channels;
+            dst->ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
+        }
+    } else {
+#endif
+    ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
+    if (ret < 0)
+        goto fail;
+#if FF_API_OLD_CHANNEL_LAYOUT
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    wipe_side_data(dst);
+    av_dict_free(&dst->metadata);
+    ret = frame_copy_props(dst, src, 0);
+    if (ret < 0)
+        goto fail;
+
+    /* duplicate the frame data if it's not refcounted */
+    if (!src->buf[0]) {
+        for (i = 0; i < FF_ARRAY_ELEMS(dst->buf); i++)
+            av_buffer_unref(&dst->buf[i]);
+        for (i = 0; i < dst->nb_extended_buf; i++)
+            av_buffer_unref(&dst->extended_buf[i]);
+        av_freep(&dst->extended_buf);
+
+        memset(dst->data, 0, sizeof(dst->data));
+        if (dst->extended_data != dst->data)
+            av_freep(&dst->extended_data);
+
+        ret = av_frame_get_buffer(dst, 0);
+        if (ret < 0)
+            goto fail;
+
+        ret = av_frame_copy(dst, src);
+        if (ret < 0)
+            goto fail;
+
+        ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx);
+        if (ret < 0)
+            goto fail;
+
+        return 0;
+    }
+
+    /* replace the buffers */
+    for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
+        ret = av_buffer_replace(&dst->buf[i], src->buf[i]);
+        if (ret < 0)
+            goto fail;
+    }
+
+    if (src->extended_buf) {
+        if (dst->nb_extended_buf != src->nb_extended_buf) {
+            int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf);
+            void *tmp;
+
+            for (i = nb_extended_buf; i < dst->nb_extended_buf; i++)
+                av_buffer_unref(&dst->extended_buf[i]);
+
+            tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf),
+                                   src->nb_extended_buf);
+            if (!tmp) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            dst->extended_buf = tmp;
+            dst->nb_extended_buf = src->nb_extended_buf;
+
+            memset(&dst->extended_buf[nb_extended_buf], 0,
+                   (src->nb_extended_buf - nb_extended_buf) * sizeof(*dst->extended_buf));
+        }
+
+        for (i = 0; i < src->nb_extended_buf; i++) {
+            ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]);
+            if (ret < 0)
+                goto fail;
+        }
+    } else if (dst->extended_buf) {
+        for (i = 0; i < dst->nb_extended_buf; i++)
+            av_buffer_unref(&dst->extended_buf[i]);
+        av_freep(&dst->extended_buf);
+    }
+
+    ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx);
+    if (ret < 0)
+        goto fail;
+
+    if (dst->extended_data != dst->data)
+        av_freep(&dst->extended_data);
+
+    if (src->extended_data != src->data) {
+        int ch = src->ch_layout.nb_channels;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (!ch) {
+            ch = src->channels;
+            CHECK_CHANNELS_CONSISTENCY(src);
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        if (!ch) {
+            ret = AVERROR(EINVAL);
+            goto fail;
+        }
+
+        dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
+        if (!dst->extended_data) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
+    } else
+        dst->extended_data = dst->data;
+
+    memcpy(dst->data,     src->data,     sizeof(src->data));
+    memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
+
+    return 0;
+
+fail:
+    av_frame_unref(dst);
+    return ret;
+}
+
 AVFrame *av_frame_clone(const AVFrame *src)
 {
     AVFrame *ret = av_frame_alloc();
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 33fac2054c..a971b1655e 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -752,6 +752,23 @@ void av_frame_free(AVFrame **frame);
  */
 int av_frame_ref(AVFrame *dst, const AVFrame *src);
 
+/**
+ * Ensure the destination frame refers to the same data described by the source
+ * frame by creating a new reference for each AVBufferRef from src if they
+ * differ from those in dst, or if src is not reference counted, by allocating
+ * new buffers and copying data.
+ *
+ * Frame properties on dst will be replaced by those from src.
+ *
+ * @param src The source frame. If there's data described in it, it must be
+ *            reference counted.
+ * @param dst The destination frame.
+ *
+ * @return 0 on success, a negative AVERROR on error. On error, dst is
+ *         unreferenced.
+ */
+int av_frame_replace(AVFrame *dst, const AVFrame *src);
+
 /**
  * Create a new frame that references the same data as src.
  *
-- 
2.36.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-06-07 12:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-05 15:28 [FFmpeg-devel] [PATCH] avutil/frame: add av_frame_replace James Almer
2022-06-05 15:42 ` Andreas Rheinhardt
2022-06-05 15:52   ` James Almer
2022-06-05 17:44   ` [FFmpeg-devel] [PATCH v2] " James Almer
2022-06-07 10:21     ` Anton Khirnov
2022-06-07 11:39       ` James Almer
2022-06-07 11:47         ` Anton Khirnov
2022-06-07 12:02           ` [FFmpeg-devel] [PATCH v3] " James Almer
2022-06-07 12:18             ` Nicolas George
2022-06-07 12:22               ` James Almer
2022-06-07 12:23                 ` Nicolas George

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git