* [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
* Re: [FFmpeg-devel] [PATCH] avutil/frame: add av_frame_replace
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
0 siblings, 2 replies; 11+ messages in thread
From: Andreas Rheinhardt @ 2022-06-05 15:42 UTC (permalink / raw)
To: ffmpeg-devel
James Almer:
> 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.
>
Apparently, you didn't get my point last time: What happens if dst and
src coincide did not mean "what happpens if the data both frames refer
to already coincides"; it meant "what happens if src == dst?" (so that
there is only one AVFrame involved). You either disallow this altogether
or you support it. This patch (and the last one) does neither.
> 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;
Why don't you use "for (int i = 0;" loop variables?
> +
> + 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.
The text above says "if src is not reference counted, by allocating new
buffers and copying data".
> + * @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.
> *
_______________________________________________
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
* Re: [FFmpeg-devel] [PATCH] avutil/frame: add av_frame_replace
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
1 sibling, 0 replies; 11+ messages in thread
From: James Almer @ 2022-06-05 15:52 UTC (permalink / raw)
To: ffmpeg-devel
On 6/5/2022 12:42 PM, Andreas Rheinhardt wrote:
> James Almer:
>> 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.
>>
>
> Apparently, you didn't get my point last time: What happens if dst and
> src coincide did not mean "what happpens if the data both frames refer
> to already coincides"; it meant "what happens if src == dst?" (so that
> there is only one AVFrame involved). You either disallow this altogether
> or you support it. This patch (and the last one) does neither.
Ok, will disallow this with
if (dst == src)
return AVERROR(EINVAL);
How does av_frame_ref() handle this scenario, for that matter? The
checks i see to ensure dst is clean (and thus one could assume is
different than src) are non strict with av_assert1().
>
>> 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;
>
> Why don't you use "for (int i = 0;" loop variables?
Because i copied this from av_frame_ref(). Will change it.
>
>> +
>> + 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.
>
> The text above says "if src is not reference counted, by allocating new
> buffers and copying data".
Remnant from the previous version. Will fix.
>
>> + * @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.
>> *
>
> _______________________________________________
> 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".
_______________________________________________
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
* [FFmpeg-devel] [PATCH v2] avutil/frame: add av_frame_replace
2022-06-05 15:42 ` Andreas Rheinhardt
2022-06-05 15:52 ` James Almer
@ 2022-06-05 17:44 ` James Almer
2022-06-07 10:21 ` Anton Khirnov
1 sibling, 1 reply; 11+ messages in thread
From: James Almer @ 2022-06-05 17:44 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
Now disallowing src == dst.
libavutil/frame.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++
libavutil/frame.h | 13 ++++
2 files changed, 160 insertions(+)
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 4c16488c66..86f9dcb59a 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -461,6 +461,153 @@ fail:
return ret;
}
+int av_frame_replace(AVFrame *dst, const AVFrame *src)
+{
+ int ret = 0;
+
+ if (dst == src)
+ return AVERROR(EINVAL);
+
+ 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 (int i = 0; i < FF_ARRAY_ELEMS(dst->buf); i++)
+ av_buffer_unref(&dst->buf[i]);
+ for (int 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 (int 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 (int 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 (int 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 (int 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..e5c10e2b66 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -752,6 +752,19 @@ 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.
+ *
+ * @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
* Re: [FFmpeg-devel] [PATCH v2] avutil/frame: add av_frame_replace
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
0 siblings, 1 reply; 11+ messages in thread
From: Anton Khirnov @ 2022-06-07 10:21 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting James Almer (2022-06-05 19:44:58)
> +
> + /* duplicate the frame data if it's not refcounted */
> + if (!src->buf[0]) {
> + for (int i = 0; i < FF_ARRAY_ELEMS(dst->buf); i++)
> + av_buffer_unref(&dst->buf[i]);
> + for (int 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;
This looks suspicious, since we just allocated normal buffers for dst.
Also, can't t this whole block be replaced by just
if (!src->buf[0]) {
av_frame_unref(dst);
return av_frame_ref(dst, src);
}
at the beginning of this function?
> + 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);
nit: av_memdup()?
> + } 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..e5c10e2b66 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -752,6 +752,19 @@ 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.
> + *
> + * @return 0 on success, a negative AVERROR on error. On error, dst is
> + * unreferenced.
> + */
> +int av_frame_replace(AVFrame *dst, const AVFrame *src);
An important property of av_buffer_replace() is that it's equivalent to
av_buffer_unref(dst) when src is NULL. It would probably be desirable
for av_frame_replace() to work the same way - currently it will try to
call av_frame_get_buffer() with invalid parameters and fail.
--
Anton Khirnov
_______________________________________________
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
* Re: [FFmpeg-devel] [PATCH v2] avutil/frame: add av_frame_replace
2022-06-07 10:21 ` Anton Khirnov
@ 2022-06-07 11:39 ` James Almer
2022-06-07 11:47 ` Anton Khirnov
0 siblings, 1 reply; 11+ messages in thread
From: James Almer @ 2022-06-07 11:39 UTC (permalink / raw)
To: ffmpeg-devel
On 6/7/2022 7:21 AM, Anton Khirnov wrote:
> Quoting James Almer (2022-06-05 19:44:58)
>> +
>> + /* duplicate the frame data if it's not refcounted */
>> + if (!src->buf[0]) {
>> + for (int i = 0; i < FF_ARRAY_ELEMS(dst->buf); i++)
>> + av_buffer_unref(&dst->buf[i]);
>> + for (int 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;
>
> This looks suspicious, since we just allocated normal buffers for dst.
Right, removed.
> Also, can't t this whole block be replaced by just
>
> if (!src->buf[0]) {
> av_frame_unref(dst);
> return av_frame_ref(dst, src);
> }
>
> at the beginning of this function?
Yes, but i was copying how av_frame_ref() handled this scenario, albeit
with a bit more of code.
Will change, but it will need to be re-added if someone at some point
decides to implement replace for side 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);
>
> nit: av_memdup()?
>
>> + } 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..e5c10e2b66 100644
>> --- a/libavutil/frame.h
>> +++ b/libavutil/frame.h
>> @@ -752,6 +752,19 @@ 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.
>> + *
>> + * @return 0 on success, a negative AVERROR on error. On error, dst is
>> + * unreferenced.
>> + */
>> +int av_frame_replace(AVFrame *dst, const AVFrame *src);
>
> An important property of av_buffer_replace() is that it's equivalent to
> av_buffer_unref(dst) when src is NULL. It would probably be desirable
> for av_frame_replace() to work the same way - currently it will try to
> call av_frame_get_buffer() with invalid parameters and fail.
Should it really accept NULL as src, or you meant a recently
allocated/unreff'd frame as src (So src->data[0] == NULL)?
_______________________________________________
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
* Re: [FFmpeg-devel] [PATCH v2] avutil/frame: add av_frame_replace
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
0 siblings, 1 reply; 11+ messages in thread
From: Anton Khirnov @ 2022-06-07 11:47 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting James Almer (2022-06-07 13:39:55)
> >> diff --git a/libavutil/frame.h b/libavutil/frame.h
> >> index 33fac2054c..e5c10e2b66 100644
> >> --- a/libavutil/frame.h
> >> +++ b/libavutil/frame.h
> >> @@ -752,6 +752,19 @@ 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.
> >> + *
> >> + * @return 0 on success, a negative AVERROR on error. On error, dst is
> >> + * unreferenced.
> >> + */
> >> +int av_frame_replace(AVFrame *dst, const AVFrame *src);
> >
> > An important property of av_buffer_replace() is that it's equivalent to
> > av_buffer_unref(dst) when src is NULL. It would probably be desirable
> > for av_frame_replace() to work the same way - currently it will try to
> > call av_frame_get_buffer() with invalid parameters and fail.
>
> Should it really accept NULL as src, or you meant a recently
> allocated/unreff'd frame as src (So src->data[0] == NULL)?
I mean an equivalent of NULL buffer, so an empty (but non-NULL) frame.
So all of src->data[] == NULL (some hwaccel pixfmts store things only in
data[3] for hysterical raisins).
--
Anton Khirnov
_______________________________________________
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
* [FFmpeg-devel] [PATCH v3] avutil/frame: add av_frame_replace
2022-06-07 11:47 ` Anton Khirnov
@ 2022-06-07 12:02 ` James Almer
2022-06-07 12:18 ` Nicolas George
0 siblings, 1 reply; 11+ messages in thread
From: James Almer @ 2022-06-07 12:02 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavutil/frame.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++
libavutil/frame.h | 13 +++++
2 files changed, 145 insertions(+)
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 4c16488c66..293bf6a437 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -461,6 +461,138 @@ fail:
return ret;
}
+int av_frame_replace(AVFrame *dst, const AVFrame *src)
+{
+ int ret = 0;
+
+ if (dst == src)
+ return AVERROR(EINVAL);
+
+ if (!src->buf[0]) {
+ av_frame_unref(dst);
+
+ /* duplicate the frame data if it's not refcounted */
+ if ( src->data[0] || src->data[1]
+ || src->data[2] || src->data[3])
+ return av_frame_ref(dst, src);
+ return 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;
+
+ /* replace the buffers */
+ for (int 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 (int 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 (int 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 (int 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;
+ }
+
+ if (ch > SIZE_MAX / sizeof(*dst->extended_data))
+ goto fail;
+
+ dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch);
+ if (!dst->extended_data) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ } 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..e5c10e2b66 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -752,6 +752,19 @@ 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.
+ *
+ * @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
* Re: [FFmpeg-devel] [PATCH v3] avutil/frame: add av_frame_replace
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
0 siblings, 1 reply; 11+ messages in thread
From: Nicolas George @ 2022-06-07 12:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 515 bytes --]
James Almer (12022-06-07):
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> libavutil/frame.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++
> libavutil/frame.h | 13 +++++
> 2 files changed, 145 insertions(+)
I do not like having a new function without anything that uses it. It
results in several cases in a function that is not really useful because
of a small design flaw. Can you update other parts of the code to make
use of the new function?
Regards,
--
Nicolas George
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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
* Re: [FFmpeg-devel] [PATCH v3] avutil/frame: add av_frame_replace
2022-06-07 12:18 ` Nicolas George
@ 2022-06-07 12:22 ` James Almer
2022-06-07 12:23 ` Nicolas George
0 siblings, 1 reply; 11+ messages in thread
From: James Almer @ 2022-06-07 12:22 UTC (permalink / raw)
To: ffmpeg-devel
On 6/7/2022 9:18 AM, Nicolas George wrote:
> James Almer (12022-06-07):
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>> libavutil/frame.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++
>> libavutil/frame.h | 13 +++++
>> 2 files changed, 145 insertions(+)
>
> I do not like having a new function without anything that uses it. It
> results in several cases in a function that is not really useful because
> of a small design flaw. Can you update other parts of the code to make
> use of the new function?
>
> Regards,
I did the first time i wrote this function and sent it last August. See
http://ffmpeg.org/pipermail/ffmpeg-devel/2021-August/283448.html
http://ffmpeg.org/pipermail/ffmpeg-devel/2021-August/283449.html
I can rebase them if they don't apply anymore, but either way, Anton
asked me to resurrect this patch since he intends to use this function too.
_______________________________________________
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
* Re: [FFmpeg-devel] [PATCH v3] avutil/frame: add av_frame_replace
2022-06-07 12:22 ` James Almer
@ 2022-06-07 12:23 ` Nicolas George
0 siblings, 0 replies; 11+ messages in thread
From: Nicolas George @ 2022-06-07 12:23 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 488 bytes --]
James Almer (12022-06-07):
> I did the first time i wrote this function and sent it last August. See
> http://ffmpeg.org/pipermail/ffmpeg-devel/2021-August/283448.html
> http://ffmpeg.org/pipermail/ffmpeg-devel/2021-August/283449.html
>
> I can rebase them if they don't apply anymore, but either way, Anton asked
> me to resurrect this patch since he intends to use this function too.
Ok, thanks for pointing it, I have no objection then.
Regards,
--
Nicolas George
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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