Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Seungha Yang
gst-editing-services
Commits
3f95c3aa
Commit
3f95c3aa
authored
Nov 02, 2018
by
Thibault Saunier
🌵
Browse files
ges: Check the thread from which our API is used
And add some missing API guards
parent
27100fcc
Changes
3
Hide whitespace changes
Inline
Side-by-side
ges/ges-pipeline.c
View file @
3f95c3aa
...
...
@@ -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
);
};
ges/ges-timeline.c
View file @
3f95c3aa
...
...
@@ -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
);
...
...
ges/ges-track.c
View file @
3f95c3aa
...
...
@@ -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
;
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment