[PATCH 1/3 v4] avutil/frame: add av_frame_replace
Signed-off-by: James Almer <jamrial@gmail.com> --- libavutil/frame.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.h | 13 +++++ 2 files changed, 137 insertions(+) diff --git a/libavutil/frame.c b/libavutil/frame.c index de4ad1f94d..864c66371f 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -471,6 +471,130 @@ 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 = dst->ch_layout.nb_channels; + + 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 6d9563bc5d..859ccf6c6c 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -762,6 +762,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.37.1
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/pthread_frame.c | 30 ++++++++++++++++++++++++++++++ libavcodec/threadframe.h | 3 +++ libavcodec/utils.c | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index a54d16fee4..ef447ee699 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -1071,6 +1071,36 @@ int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) return ret; } +int ff_thread_replace_frame(AVCodecContext *avctx, ThreadFrame *dst, + const ThreadFrame *src) +{ + int ret; +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS + int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || + THREAD_SAFE_CALLBACKS(avctx); +FF_ENABLE_DEPRECATION_WARNINGS + + if (!can_direct_free) + ff_thread_release_ext_buffer(avctx, dst); +#endif + + dst->owner[0] = src->owner[0]; + dst->owner[1] = src->owner[1]; + + ret = av_frame_replace(dst->f, src->f); + if (ret < 0) + return ret; + + ret = av_buffer_replace(&dst->progress, src->progress); + if (ret < 0) { + ff_thread_release_ext_buffer(dst->owner[0], dst); + return ret; + } + + return 0; +} + void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f) { #if FF_API_THREAD_SAFE_CALLBACKS diff --git a/libavcodec/threadframe.h b/libavcodec/threadframe.h index 100e068e06..a8403c8976 100644 --- a/libavcodec/threadframe.h +++ b/libavcodec/threadframe.h @@ -84,4 +84,7 @@ void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f); int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src); +int ff_thread_replace_frame(AVCodecContext *avctx, ThreadFrame *dst, + const ThreadFrame *src); + #endif diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e73e3a7d08..44ed19458c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -928,6 +928,27 @@ int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) return ff_get_buffer(avctx, f->f, flags); } +int ff_thread_replace_frame(AVCodecContext *avctx, , ThreadFrame *dst, + const ThreadFrame *src) +{ + int ret; + + dst->owner[0] = src->owner[0]; + dst->owner[1] = src->owner[1]; + + ret = av_frame_replace(dst->f, src->f); + if (ret < 0) + return ret; + + ret = av_buffer_replace(&dst->progress, src->progress); + if (ret < 0) { + ff_thread_release_ext_buffer(dst->owner[0], dst); + return ret; + } + + return 0; +} + void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f) { if (f) -- 2.37.1
On Wed, Aug 03, 2022 at 01:02:47PM -0300, James Almer wrote:
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/pthread_frame.c | 30 ++++++++++++++++++++++++++++++ libavcodec/threadframe.h | 3 +++ libavcodec/utils.c | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+) [...] diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e73e3a7d08..44ed19458c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -928,6 +928,27 @@ int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) return ff_get_buffer(avctx, f->f, flags); }
+int ff_thread_replace_frame(AVCodecContext *avctx, , ThreadFrame *dst, ^^^ typo
thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB There will always be a question for which you do not know the correct answer.
On 8/4/2022 3:33 PM, Michael Niedermayer wrote:
On Wed, Aug 03, 2022 at 01:02:47PM -0300, James Almer wrote:
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/pthread_frame.c | 30 ++++++++++++++++++++++++++++++ libavcodec/threadframe.h | 3 +++ libavcodec/utils.c | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+) [...] diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e73e3a7d08..44ed19458c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -928,6 +928,27 @@ int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) return ff_get_buffer(avctx, f->f, flags); }
+int ff_thread_replace_frame(AVCodecContext *avctx, , ThreadFrame *dst, ^^^ typo
thx
Fixed locally.
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/h264_picture.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c index 2661ff4698..dcaf0fdb0a 100644 --- a/libavcodec/h264_picture.c +++ b/libavcodec/h264_picture.c @@ -154,8 +154,7 @@ int ff_h264_replace_picture(H264Context *h, H264Picture *dst, const H264Picture av_assert0(src->tf.f == src->f); dst->tf.f = dst->f; - ff_thread_release_ext_buffer(h->avctx, &dst->tf); - ret = ff_thread_ref_frame(&dst->tf, &src->tf); + ret = ff_thread_replace_frame(h->avctx, &dst->tf, &src->tf); if (ret < 0) goto fail; -- 2.37.1
On 8/3/2022 1:02 PM, James Almer wrote:
Signed-off-by: James Almer <jamrial@gmail.com> --- libavutil/frame.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.h | 13 +++++ 2 files changed, 137 insertions(+)
diff --git a/libavutil/frame.c b/libavutil/frame.c index de4ad1f94d..864c66371f 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -471,6 +471,130 @@ fail: return ret; }
Will apply set (More than half a year later).
participants (2)
-
James Almer -
Michael Niedermayer