videotestsrc: add mutex around cache buffer to prevent race condition

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6890>
This commit is contained in:
Joshua Breeden 2024-05-15 10:58:57 -07:00 committed by Backport Bot
parent 43dcbd5bf9
commit 27c95064aa
2 changed files with 27 additions and 2 deletions

View file

@ -112,6 +112,8 @@ G_DEFINE_TYPE (GstVideoTestSrc, gst_video_test_src, GST_TYPE_PUSH_SRC);
GST_ELEMENT_REGISTER_DEFINE (videotestsrc, "videotestsrc", GST_ELEMENT_REGISTER_DEFINE (videotestsrc, "videotestsrc",
GST_RANK_NONE, GST_TYPE_VIDEO_TEST_SRC); GST_RANK_NONE, GST_TYPE_VIDEO_TEST_SRC);
static void gst_video_test_src_finalize (GObject * object);
static void gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc, static void gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc,
int pattern_type); int pattern_type);
static void gst_video_test_src_set_property (GObject * object, guint prop_id, static void gst_video_test_src_set_property (GObject * object, guint prop_id,
@ -246,6 +248,7 @@ gst_video_test_src_class_init (GstVideoTestSrcClass * klass)
gobject_class->set_property = gst_video_test_src_set_property; gobject_class->set_property = gst_video_test_src_set_property;
gobject_class->get_property = gst_video_test_src_get_property; gobject_class->get_property = gst_video_test_src_get_property;
gobject_class->finalize = gst_video_test_src_finalize;
g_object_class_install_property (gobject_class, PROP_PATTERN, g_object_class_install_property (gobject_class, PROP_PATTERN,
g_param_spec_enum ("pattern", "Pattern", g_param_spec_enum ("pattern", "Pattern",
@ -405,6 +408,15 @@ gst_video_test_src_init (GstVideoTestSrc * src)
src->motion_type = DEFAULT_MOTION_TYPE; src->motion_type = DEFAULT_MOTION_TYPE;
src->flip = DEFAULT_FLIP; src->flip = DEFAULT_FLIP;
g_mutex_init (&src->cache_lock);
}
static void
gst_video_test_src_finalize (GObject * object)
{
GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object);
g_mutex_clear (&src->cache_lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static GstCaps * static GstCaps *
@ -744,9 +756,11 @@ gst_video_test_src_set_property (GObject * object, guint prop_id,
} }
if (invalidate) { if (invalidate) {
g_mutex_lock (&src->cache_lock);
/* Property change invalidated the current pattern - check if it's static now or not */ /* Property change invalidated the current pattern - check if it's static now or not */
src->have_static_pattern = gst_video_test_src_is_static_pattern (src); src->have_static_pattern = gst_video_test_src_is_static_pattern (src);
gst_clear_buffer (&src->cached); gst_clear_buffer (&src->cached);
g_mutex_unlock (&src->cache_lock);
} }
} }
@ -1026,7 +1040,9 @@ gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
videotestsrc->running_time = 0; videotestsrc->running_time = 0;
videotestsrc->n_frames = 0; videotestsrc->n_frames = 0;
g_mutex_lock (&videotestsrc->cache_lock);
gst_clear_buffer (&videotestsrc->cached); gst_clear_buffer (&videotestsrc->cached);
g_mutex_unlock (&videotestsrc->cache_lock);
GST_OBJECT_UNLOCK (videotestsrc); GST_OBJECT_UNLOCK (videotestsrc);
@ -1262,12 +1278,15 @@ gst_video_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
if (src->have_static_pattern) { if (src->have_static_pattern) {
GstVideoFrame sframe, dframe; GstVideoFrame sframe, dframe;
g_mutex_lock (&src->cache_lock);
if (src->cached == NULL) { if (src->cached == NULL) {
src->cached = gst_buffer_new_allocate (NULL, src->info.size, NULL); src->cached = gst_buffer_new_allocate (NULL, src->info.size, NULL);
ret = fill_image (GST_PUSH_SRC (src), src->cached); ret = fill_image (GST_PUSH_SRC (src), src->cached);
if (G_UNLIKELY (ret != GST_FLOW_OK)) if (G_UNLIKELY (ret != GST_FLOW_OK)) {
g_mutex_unlock (&src->cache_lock);
goto fill_failed; goto fill_failed;
}
} else { } else {
GST_LOG_OBJECT (src, "Reusing cached pattern buffer"); GST_LOG_OBJECT (src, "Reusing cached pattern buffer");
} }
@ -1279,11 +1298,14 @@ gst_video_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
gst_video_frame_map (&sframe, &src->info, src->cached, GST_MAP_READ); gst_video_frame_map (&sframe, &src->info, src->cached, GST_MAP_READ);
gst_video_frame_map (&dframe, &src->info, buffer, GST_MAP_WRITE); gst_video_frame_map (&dframe, &src->info, buffer, GST_MAP_WRITE);
if (!gst_video_frame_copy (&dframe, &sframe)) if (!gst_video_frame_copy (&dframe, &sframe)) {
g_mutex_unlock (&src->cache_lock);
goto copy_failed; goto copy_failed;
}
gst_video_frame_unmap (&sframe); gst_video_frame_unmap (&sframe);
gst_video_frame_unmap (&dframe); gst_video_frame_unmap (&dframe);
g_mutex_unlock (&src->cache_lock);
} else { } else {
ret = fill_image (GST_PUSH_SRC (src), buffer); ret = fill_image (GST_PUSH_SRC (src), buffer);
if (G_UNLIKELY (ret != GST_FLOW_OK)) if (G_UNLIKELY (ret != GST_FLOW_OK))
@ -1383,7 +1405,9 @@ gst_video_test_src_stop (GstBaseSrc * basesrc)
src->n_lines = 0; src->n_lines = 0;
src->lines = NULL; src->lines = NULL;
g_mutex_lock (&src->cache_lock);
gst_clear_buffer (&src->cached); gst_clear_buffer (&src->cached);
g_mutex_unlock (&src->cache_lock);
return TRUE; return TRUE;
} }

View file

@ -209,6 +209,7 @@ struct _GstVideoTestSrc {
/* cached buffer used for static patterns that don't change */ /* cached buffer used for static patterns that don't change */
GstBuffer *cached; GstBuffer *cached;
GMutex cache_lock;
gboolean have_static_pattern; gboolean have_static_pattern;
}; };