diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.c b/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.c index a86c70a6e4..95adf3643f 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.c @@ -266,6 +266,12 @@ gst_video_frame_unmap (GstVideoFrame * frame) meta = frame->meta; flags = frame->map[0].flags; + /* Allow to unmap even if not mapped, to work nicely with + * g_auto (GstVideoFrame) frame = GST_VIDEO_FRAME_INIT; + * This is also more consistent with gst_buffer_unmap() */ + if (G_UNLIKELY (buffer == NULL)) + return; + if (meta) { for (i = 0; i < frame->info.finfo->n_planes; i++) { gst_video_meta_unmap (meta, i, &frame->map[i]); diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.h b/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.h index f3925c47de..6f026305f3 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/video-frame.h @@ -93,6 +93,16 @@ struct _GstVideoFrame { gpointer _gst_reserved[GST_PADDING]; }; +/** + * GST_VIDEO_FRAME_INIT: + * + * Initializer for #GstVideoFrame + * + * Since: 1.22 + */ +#define GST_VIDEO_FRAME_INIT { { NULL, }, } + + GST_VIDEO_API gboolean gst_video_frame_map (GstVideoFrame *frame, const GstVideoInfo *info, GstBuffer *buffer, GstMapFlags flags); @@ -249,6 +259,8 @@ typedef enum { /* 8 more flags possible afterwards */ } GstVideoFrameMapFlags; +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GstVideoFrame, gst_video_frame_unmap) + G_END_DECLS #endif /* __GST_VIDEO_FRAME_H__ */ diff --git a/subprojects/gst-plugins-base/tests/check/libs/video.c b/subprojects/gst-plugins-base/tests/check/libs/video.c index 42674f4eb2..f17322da11 100644 --- a/subprojects/gst-plugins-base/tests/check/libs/video.c +++ b/subprojects/gst-plugins-base/tests/check/libs/video.c @@ -4042,6 +4042,34 @@ GST_START_TEST (test_video_extrapolate_stride) GST_END_TEST; +GST_START_TEST (test_auto_video_frame_unmap) +{ +#ifdef g_auto + g_autoptr (GstBuffer) buf = NULL; + GstVideoInfo info; + + fail_unless (gst_video_info_set_format (&info, GST_VIDEO_FORMAT_ENCODED, 10, + 10)); + buf = gst_buffer_new_and_alloc (info.size); + + { + // unmap should be no-op + g_auto (GstVideoFrame) frame = GST_VIDEO_FRAME_INIT; + fail_unless (frame.buffer == NULL); + } + + { + g_auto (GstVideoFrame) frame = GST_VIDEO_FRAME_INIT; + gst_video_frame_map (&frame, &info, buf, GST_MAP_READ); + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (buf), 2); + } + + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (buf), 1); + +#endif +} + +GST_END_TEST; static Suite * video_suite (void) @@ -4098,6 +4126,7 @@ video_suite (void) tcase_add_test (tc_chain, test_video_flags); tcase_add_test (tc_chain, test_video_make_raw_caps); tcase_add_test (tc_chain, test_video_extrapolate_stride); + tcase_add_test (tc_chain, test_auto_video_frame_unmap); return s; }