tagsetter: protect tagsetter operations with a lock

So we don't crash when a muxer tries to add tags from two
threads at the same time, eg. because it received tag events
on two input pads simultaneously.

See #619533.
This commit is contained in:
Tim-Philipp Müller 2010-05-24 18:16:19 +01:00
parent ccaadae492
commit 99eb992bc0

View file

@ -86,6 +86,7 @@ typedef struct
{
GstTagMergeMode mode;
GstTagList *list;
GStaticMutex lock;
} GstTagData;
GType
@ -130,6 +131,8 @@ gst_tag_data_free (gpointer p)
if (data->list)
gst_tag_list_free (data->list);
g_static_mutex_free (&data->lock);
g_slice_free (GstTagData, data);
}
@ -141,6 +144,7 @@ gst_tag_setter_get_data (GstTagSetter * setter)
data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
if (!data) {
data = g_slice_new (GstTagData);
g_static_mutex_init (&data->lock);
data->list = NULL;
data->mode = GST_TAG_MERGE_KEEP;
g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data,
@ -167,10 +171,13 @@ gst_tag_setter_reset_tags (GstTagSetter * setter)
g_return_if_fail (GST_IS_TAG_SETTER (setter));
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
if (data->list) {
gst_tag_list_free (data->list);
data->list = NULL;
}
g_static_mutex_unlock (&data->lock);
}
/**
@ -192,12 +199,15 @@ gst_tag_setter_merge_tags (GstTagSetter * setter, const GstTagList * list,
g_return_if_fail (GST_IS_TAG_LIST (list));
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
if (data->list == NULL) {
if (mode != GST_TAG_MERGE_KEEP_ALL)
data->list = gst_tag_list_copy (list);
} else {
gst_tag_list_insert (data->list, list, mode);
}
g_static_mutex_unlock (&data->lock);
}
/**
@ -268,10 +278,14 @@ gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode,
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
if (!data->list)
data->list = gst_tag_list_new ();
gst_tag_list_add_valist (data->list, mode, tag, var_args);
g_static_mutex_unlock (&data->lock);
}
/**
@ -294,10 +308,15 @@ gst_tag_setter_add_tag_valist_values (GstTagSetter * setter,
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
if (!data->list)
data->list = gst_tag_list_new ();
gst_tag_list_add_valist_values (data->list, mode, tag, var_args);
g_static_mutex_unlock (&data->lock);
}
/**
@ -321,10 +340,15 @@ gst_tag_setter_add_tag_value (GstTagSetter * setter,
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
if (!data->list)
data->list = gst_tag_list_new ();
gst_tag_list_add_value (data->list, mode, tag, value);
g_static_mutex_unlock (&data->lock);
}
/**
@ -334,6 +358,8 @@ gst_tag_setter_add_tag_value (GstTagSetter * setter,
* Returns the current list of tags the setter uses. The list should not be
* modified or freed.
*
* This function is not thread-safe.
*
* Returns: a current snapshot of the taglist used in the setter
* or NULL if none is used.
*/
@ -357,10 +383,16 @@ gst_tag_setter_get_tag_list (GstTagSetter * setter)
void
gst_tag_setter_set_tag_merge_mode (GstTagSetter * setter, GstTagMergeMode mode)
{
GstTagData *data;
g_return_if_fail (GST_IS_TAG_SETTER (setter));
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
gst_tag_setter_get_data (setter)->mode = mode;
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
data->mode = mode;
g_static_mutex_unlock (&data->lock);
}
/**
@ -375,7 +407,16 @@ gst_tag_setter_set_tag_merge_mode (GstTagSetter * setter, GstTagMergeMode mode)
GstTagMergeMode
gst_tag_setter_get_tag_merge_mode (GstTagSetter * setter)
{
GstTagMergeMode mode;
GstTagData *data;
g_return_val_if_fail (GST_IS_TAG_SETTER (setter), FALSE);
return gst_tag_setter_get_data (setter)->mode;
data = gst_tag_setter_get_data (setter);
g_static_mutex_lock (&data->lock);
mode = data->mode;
g_static_mutex_unlock (&data->lock);
return mode;
}