Commit 3f95c3aa authored by Thibault Saunier's avatar Thibault Saunier 🌵
Browse files

ges: Check the thread from which our API is used

And add some missing API guards
parent 27100fcc
......@@ -44,6 +44,7 @@ GST_DEBUG_CATEGORY_STATIC (ges_pipeline_debug);
#define DEFAULT_TIMELINE_MODE GES_PIPELINE_MODE_PREVIEW
#define IN_RENDERING_MODE(timeline) ((timeline->priv->mode) & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER))
#define CHECK_THREAD(pipeline) g_assert(pipeline->priv->valid_thread == g_thread_self())
/* Structure corresponding to a timeline - sink link */
......@@ -74,6 +75,8 @@ struct _GESPipelinePrivate
GList *not_rendered_tracks;
GstEncodingProfile *profile;
GThread *valid_thread;
};
enum
......@@ -370,6 +373,7 @@ ges_pipeline_init (GESPipeline * self)
GST_INFO_OBJECT (self, "Creating new 'playsink'");
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GES_TYPE_PIPELINE, GESPipelinePrivate);
self->priv->valid_thread = g_thread_self ();
self->priv->playsink =
gst_element_factory_make ("playsink", "internal-sinks");
......@@ -1015,6 +1019,7 @@ ges_pipeline_set_timeline (GESPipeline * pipeline, GESTimeline * timeline)
g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE);
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (pipeline->priv->timeline == NULL, FALSE);
CHECK_THREAD (pipeline);
GST_DEBUG ("pipeline:%p, timeline:%p", timeline, pipeline);
......@@ -1058,6 +1063,7 @@ ges_pipeline_set_render_settings (GESPipeline * pipeline,
GstEncodingProfile *set_profile;
g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE);
CHECK_THREAD (pipeline);
/* FIXME Properly handle multi track, for now GESPipeline
* only hanles single track per type, so we should just set the
......@@ -1157,6 +1163,7 @@ ges_pipeline_set_mode (GESPipeline * pipeline, GESPipelineFlags mode)
GList *tmp;
g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE);
CHECK_THREAD (pipeline);
GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d",
pipeline->priv->mode, mode);
......@@ -1283,6 +1290,7 @@ ges_pipeline_get_thumbnail (GESPipeline * self, GstCaps * caps)
GstElement *sink;
g_return_val_if_fail (GES_IS_PIPELINE (self), FALSE);
CHECK_THREAD (self);
sink = self->priv->playsink;
......@@ -1320,6 +1328,7 @@ ges_pipeline_save_thumbnail (GESPipeline * self, int width, int
gboolean res = TRUE;
g_return_val_if_fail (GES_IS_PIPELINE (self), FALSE);
CHECK_THREAD (self);
caps = gst_caps_from_string (format);
......@@ -1376,6 +1385,7 @@ ges_pipeline_get_thumbnail_rgb24 (GESPipeline * self, gint width, gint height)
GstCaps *caps;
g_return_val_if_fail (GES_IS_PIPELINE (self), FALSE);
CHECK_THREAD (self);
caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
"RGB", NULL);
......@@ -1409,6 +1419,7 @@ ges_pipeline_preview_get_video_sink (GESPipeline * self)
GstElement *sink = NULL;
g_return_val_if_fail (GES_IS_PIPELINE (self), FALSE);
CHECK_THREAD (self);
g_object_get (self->priv->playsink, "video-sink", &sink, NULL);
......@@ -1427,6 +1438,7 @@ void
ges_pipeline_preview_set_video_sink (GESPipeline * self, GstElement * sink)
{
g_return_if_fail (GES_IS_PIPELINE (self));
CHECK_THREAD (self);
g_object_set (self->priv->playsink, "video-sink", sink, NULL);
};
......@@ -1449,6 +1461,7 @@ ges_pipeline_preview_get_audio_sink (GESPipeline * self)
GstElement *sink = NULL;
g_return_val_if_fail (GES_IS_PIPELINE (self), FALSE);
CHECK_THREAD (self);
g_object_get (self->priv->playsink, "audio-sink", &sink, NULL);
......@@ -1467,6 +1480,7 @@ void
ges_pipeline_preview_set_audio_sink (GESPipeline * self, GstElement * sink)
{
g_return_if_fail (GES_IS_PIPELINE (self));
CHECK_THREAD (self);
g_object_set (self->priv->playsink, "audio-sink", sink, NULL);
};
......@@ -87,6 +87,8 @@ GST_DEBUG_CATEGORY_STATIC (ges_timeline_debug);
g_thread_self()); \
} G_STMT_END
#define CHECK_THREAD(timeline) g_assert(timeline->priv->valid_thread == g_thread_self())
typedef struct TrackObjIters
{
GSequenceIter *iter_start;
......@@ -211,6 +213,8 @@ struct _GESTimelinePrivate
/* For ges_timeline_commit_sync */
GMutex commited_lock;
GCond commited_cond;
GThread *valid_thread;
};
/* private structure to contain our track-related information */
......@@ -697,6 +701,7 @@ ges_timeline_init (GESTimeline * self)
g_rec_mutex_init (&priv->dyn_mutex);
g_mutex_init (&priv->commited_lock);
priv->valid_thread = g_thread_self ();
}
/* Private methods */
......@@ -2945,6 +2950,9 @@ ges_timeline_save_to_uri (GESTimeline * timeline, const gchar * uri,
GList *
ges_timeline_get_groups (GESTimeline * timeline)
{
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
return timeline->priv->groups;
}
......@@ -2964,6 +2972,9 @@ ges_timeline_append_layer (GESTimeline * timeline)
guint32 priority;
GESLayer *layer;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
layer = ges_layer_new ();
priority = g_list_length (timeline->layers);
ges_layer_set_priority (layer, priority);
......@@ -2989,6 +3000,10 @@ ges_timeline_add_layer (GESTimeline * timeline, GESLayer * layer)
gboolean auto_transition;
GList *objects, *tmp;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (GES_IS_LAYER (layer), FALSE);
CHECK_THREAD (timeline);
GST_DEBUG ("timeline:%p, layer:%p", timeline, layer);
/* We can only add a layer that doesn't already belong to another timeline */
......@@ -3068,6 +3083,10 @@ ges_timeline_remove_layer (GESTimeline * timeline, GESLayer * layer)
{
GList *layer_objects, *tmp;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (GES_IS_LAYER (layer), FALSE);
CHECK_THREAD (timeline);
GST_DEBUG ("timeline:%p, layer:%p", timeline, layer);
if (G_UNLIKELY (!g_list_find (timeline->layers, layer))) {
......@@ -3128,6 +3147,10 @@ ges_timeline_add_track (GESTimeline * timeline, GESTrack * track)
TrackPrivate *tr_priv;
GList *tmp;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
CHECK_THREAD (timeline);
GST_DEBUG ("timeline:%p, track:%p", timeline, track);
/* make sure we don't already control it */
......@@ -3219,6 +3242,7 @@ ges_timeline_remove_track (GESTimeline * timeline, GESTrack * track)
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
CHECK_THREAD (timeline);
GST_DEBUG ("timeline:%p, track:%p", timeline, track);
......@@ -3290,6 +3314,8 @@ ges_timeline_get_track_for_pad (GESTimeline * timeline, GstPad * pad)
{
GList *tmp;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
LOCK_DYN (timeline);
for (tmp = timeline->priv->priv_tracks; tmp; tmp = g_list_next (tmp)) {
TrackPrivate *tr_priv = (TrackPrivate *) tmp->data;
......@@ -3349,6 +3375,7 @@ GList *
ges_timeline_get_tracks (GESTimeline * timeline)
{
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
return g_list_copy_deep (timeline->tracks, (GCopyFunc) gst_object_ref, NULL);
}
......@@ -3368,6 +3395,9 @@ ges_timeline_get_layers (GESTimeline * timeline)
{
GList *tmp, *res = NULL;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
for (tmp = timeline->layers; tmp; tmp = g_list_next (tmp)) {
res = g_list_insert_sorted (res, gst_object_ref (tmp->data),
(GCompareFunc) sort_layers);
......@@ -3465,6 +3495,8 @@ ges_timeline_commit (GESTimeline * timeline)
{
gboolean ret;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
LOCK_DYN (timeline);
ret = ges_timeline_commit_unlocked (timeline);
UNLOCK_DYN (timeline);
......@@ -3508,6 +3540,8 @@ ges_timeline_commit_sync (GESTimeline * timeline)
gboolean ret;
gboolean wait_for_signal;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
/* Let's make sure our state is stable */
gst_element_get_state (GST_ELEMENT (timeline), NULL, NULL,
GST_CLOCK_TIME_NONE);
......@@ -3549,6 +3583,7 @@ GstClockTime
ges_timeline_get_duration (GESTimeline * timeline)
{
g_return_val_if_fail (GES_IS_TIMELINE (timeline), GST_CLOCK_TIME_NONE);
CHECK_THREAD (timeline);
return timeline->priv->duration;
}
......@@ -3565,7 +3600,8 @@ ges_timeline_get_duration (GESTimeline * timeline)
gboolean
ges_timeline_get_auto_transition (GESTimeline * timeline)
{
g_return_val_if_fail (GES_IS_TIMELINE (timeline), 0);
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
CHECK_THREAD (timeline);
return timeline->priv->auto_transition;
}
......@@ -3586,6 +3622,7 @@ ges_timeline_set_auto_transition (GESTimeline * timeline,
GESLayer *layer;
g_return_if_fail (GES_IS_TIMELINE (timeline));
CHECK_THREAD (timeline);
timeline->priv->auto_transition = auto_transition;
g_object_notify (G_OBJECT (timeline), "auto-transition");
......@@ -3611,6 +3648,7 @@ GstClockTime
ges_timeline_get_snapping_distance (GESTimeline * timeline)
{
g_return_val_if_fail (GES_IS_TIMELINE (timeline), GST_CLOCK_TIME_NONE);
CHECK_THREAD (timeline);
return timeline->priv->snapping_distance;
......@@ -3629,6 +3667,7 @@ ges_timeline_set_snapping_distance (GESTimeline * timeline,
GstClockTime snapping_distance)
{
g_return_if_fail (GES_IS_TIMELINE (timeline));
CHECK_THREAD (timeline);
timeline->priv->snapping_distance = snapping_distance;
}
......@@ -3648,6 +3687,7 @@ ges_timeline_get_element (GESTimeline * timeline, const gchar * name)
GESTimelineElement *ret;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
ret = g_hash_table_lookup (timeline->priv->all_elements, name);
......@@ -3686,6 +3726,7 @@ ges_timeline_is_empty (GESTimeline * timeline)
gpointer key, value;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
CHECK_THREAD (timeline);
if (g_hash_table_size (timeline->priv->all_elements) == 0)
return TRUE;
......@@ -3718,6 +3759,9 @@ ges_timeline_get_layer (GESTimeline * timeline, guint priority)
GList *tmp;
GESLayer *layer = NULL;
g_return_val_if_fail (GES_IS_TIMELINE (timeline), NULL);
CHECK_THREAD (timeline);
for (tmp = timeline->layers; tmp; tmp = tmp->next) {
GESLayer *tmp_layer = GES_LAYER (tmp->data);
guint tmp_priority;
......@@ -3756,6 +3800,7 @@ ges_timeline_paste_element (GESTimeline * timeline,
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (element), FALSE);
CHECK_THREAD (timeline);
element_class = GES_TIMELINE_ELEMENT_GET_CLASS (element);
copied_from = ges_timeline_element_get_copied_from (element);
......
......@@ -37,6 +37,7 @@
G_DEFINE_TYPE_WITH_CODE (GESTrack, ges_track, GST_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GES_TYPE_META_CONTAINER, NULL));
#define CHECK_THREAD(track) g_assert(track->priv->valid_thread == g_thread_self())
static GstStaticPadTemplate ges_track_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src",
......@@ -80,6 +81,8 @@ struct _GESTrackPrivate
/* Virtual method to create GstElement that fill gaps */
GESCreateElementForGapFunc create_element_for_gaps;
GThread *valid_thread;
};
enum
......@@ -684,6 +687,7 @@ ges_track_init (GESTrack * self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GES_TYPE_TRACK, GESTrackPrivate);
self->priv->valid_thread = g_thread_self ();
self->priv->composition = gst_element_factory_make ("nlecomposition", NULL);
self->priv->capsfilter = gst_element_factory_make ("capsfilter", NULL);
......@@ -788,6 +792,7 @@ ges_track_set_caps (GESTrack * track, const GstCaps * caps)
gint i;
g_return_if_fail (GES_IS_TRACK (track));
CHECK_THREAD (track);
GST_DEBUG ("track:%p, caps:%" GST_PTR_FORMAT, track, caps);
g_return_if_fail (GST_IS_CAPS (caps));
......@@ -818,6 +823,7 @@ ges_track_set_restriction_caps (GESTrack * track, const GstCaps * caps)
GESTrackPrivate *priv;
g_return_if_fail (GES_IS_TRACK (track));
CHECK_THREAD (track);
GST_DEBUG ("track:%p, restriction caps:%" GST_PTR_FORMAT, track, caps);
g_return_if_fail (GST_IS_CAPS (caps));
......@@ -850,8 +856,12 @@ void
ges_track_update_restriction_caps (GESTrack * self, const GstCaps * caps)
{
guint i;
GstCaps *new_restriction_caps = gst_caps_copy (self->priv->restriction_caps);
GstCaps *new_restriction_caps;
g_return_if_fail (GES_IS_TRACK (self));
CHECK_THREAD (self);
new_restriction_caps = gst_caps_copy (self->priv->restriction_caps);
for (i = 0; i < gst_caps_get_size (caps); i++) {
GstStructure *new = gst_caps_get_structure (caps, i);
......@@ -878,6 +888,7 @@ void
ges_track_set_mixing (GESTrack * track, gboolean mixing)
{
g_return_if_fail (GES_IS_TRACK (track));
CHECK_THREAD (track);
if (!track->priv->mixing_operation) {
GST_DEBUG_OBJECT (track, "Track will be set to mixing = %d", mixing);
......@@ -927,6 +938,7 @@ ges_track_add_element (GESTrack * track, GESTrackElement * object)
{
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
CHECK_THREAD (track);
GST_DEBUG ("track:%p, object:%p", track, object);
......@@ -993,6 +1005,7 @@ ges_track_get_elements (GESTrack * track)
GList *ret = NULL;
g_return_val_if_fail (GES_IS_TRACK (track), NULL);
CHECK_THREAD (track);
g_sequence_foreach (track->priv->trackelements_by_start,
(GFunc) add_trackelement_to_list_foreach, &ret);
......@@ -1022,6 +1035,7 @@ ges_track_remove_element (GESTrack * track, GESTrackElement * object)
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
CHECK_THREAD (track);
priv = track->priv;
......@@ -1056,6 +1070,7 @@ const GstCaps *
ges_track_get_caps (GESTrack * track)
{
g_return_val_if_fail (GES_IS_TRACK (track), NULL);
CHECK_THREAD (track);
return track->priv->caps;
}
......@@ -1072,6 +1087,7 @@ const GESTimeline *
ges_track_get_timeline (GESTrack * track)
{
g_return_val_if_fail (GES_IS_TRACK (track), NULL);
CHECK_THREAD (track);
return track->priv->timeline;
}
......@@ -1111,6 +1127,7 @@ gboolean
ges_track_commit (GESTrack * track)
{
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
CHECK_THREAD (track);
track_resort_and_fill_gaps (track);
......@@ -1133,6 +1150,7 @@ ges_track_set_create_element_for_gap_func (GESTrack * track,
GESCreateElementForGapFunc func)
{
g_return_if_fail (GES_IS_TRACK (track));
CHECK_THREAD (track);
track->priv->create_element_for_gaps = func;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment