timeline: Create stable stream IDs

This commit is contained in:
Thibault Saunier 2019-06-06 17:21:01 -04:00
parent 63a49edf1f
commit 5be359cf7f
3 changed files with 75 additions and 8 deletions

View file

@ -317,8 +317,6 @@ ges_timeline_finalize (GObject * object)
G_OBJECT_CLASS (ges_timeline_parent_class)->finalize (object); G_OBJECT_CLASS (ges_timeline_parent_class)->finalize (object);
} }
static void static void
ges_timeline_handle_message (GstBin * bin, GstMessage * message) ges_timeline_handle_message (GstBin * bin, GstMessage * message)
{ {
@ -1434,9 +1432,12 @@ track_element_removed_cb (GESTrack * track,
static GstPadProbeReturn static GstPadProbeReturn
_pad_probe_cb (GstPad * mixer_pad, GstPadProbeInfo * info, _pad_probe_cb (GstPad * mixer_pad, GstPadProbeInfo * info,
GESTimeline * timeline) TrackPrivate * tr_priv)
{ {
GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
GESTimeline *timeline = tr_priv->timeline;
gchar *stream_id;
if (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START) { if (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START) {
LOCK_DYN (timeline); LOCK_DYN (timeline);
if (timeline->priv->stream_start_group_id == -1) { if (timeline->priv->stream_start_group_id == -1) {
@ -1445,7 +1446,9 @@ _pad_probe_cb (GstPad * mixer_pad, GstPadProbeInfo * info,
timeline->priv->stream_start_group_id = gst_util_group_id_next (); timeline->priv->stream_start_group_id = gst_util_group_id_next ();
} }
info->data = gst_event_make_writable (event); gst_event_unref (event);
g_object_get (tr_priv->track, "id", &stream_id, NULL);
info->data = gst_event_new_stream_start (stream_id);
gst_event_set_group_id (GST_PAD_PROBE_INFO_EVENT (info), gst_event_set_group_id (GST_PAD_PROBE_INFO_EVENT (info),
timeline->priv->stream_start_group_id); timeline->priv->stream_start_group_id);
UNLOCK_DYN (timeline); UNLOCK_DYN (timeline);
@ -1500,7 +1503,7 @@ _ghost_track_srcpad (TrackPrivate * tr_priv)
tr_priv->probe_id = gst_pad_add_probe (pad, tr_priv->probe_id = gst_pad_add_probe (pad,
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
(GstPadProbeCallback) _pad_probe_cb, tr_priv->timeline, NULL); (GstPadProbeCallback) _pad_probe_cb, tr_priv, NULL);
UNLOCK_DYN (tr_priv->timeline); UNLOCK_DYN (tr_priv->timeline);
} }

View file

@ -94,6 +94,7 @@ enum
ARG_TYPE, ARG_TYPE,
ARG_DURATION, ARG_DURATION,
ARG_MIXING, ARG_MIXING,
ARG_ID,
ARG_LAST, ARG_LAST,
TRACK_ELEMENT_ADDED, TRACK_ELEMENT_ADDED,
TRACK_ELEMENT_REMOVED, TRACK_ELEMENT_REMOVED,
@ -424,6 +425,9 @@ ges_track_get_property (GObject * object, guint property_id,
case ARG_MIXING: case ARG_MIXING:
g_value_set_boolean (value, track->priv->mixing); g_value_set_boolean (value, track->priv->mixing);
break; break;
case ARG_ID:
g_object_get_property (G_OBJECT (track->priv->composition), "id", value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
@ -448,6 +452,9 @@ ges_track_set_property (GObject * object, guint property_id,
case ARG_MIXING: case ARG_MIXING:
ges_track_set_mixing (track, g_value_get_boolean (value)); ges_track_set_mixing (track, g_value_get_boolean (value));
break; break;
case ARG_ID:
g_object_set_property (G_OBJECT (track->priv->composition), "id", value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
@ -638,6 +645,11 @@ ges_track_class_init (GESTrackClass * klass)
g_object_class_install_property (object_class, ARG_MIXING, g_object_class_install_property (object_class, ARG_MIXING,
properties[ARG_MIXING]); properties[ARG_MIXING]);
properties[ARG_ID] =
g_param_spec_string ("id", "Id", "The stream-id of the composition",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, ARG_ID, properties[ARG_ID]);
gst_element_class_add_static_pad_template (gstelement_class, gst_element_class_add_static_pad_template (gstelement_class,
&ges_track_src_pad_template); &ges_track_src_pad_template);

View file

@ -49,7 +49,7 @@ GST_DEBUG_CATEGORY_STATIC (nlecomposition_debug);
enum enum
{ {
PROP_0, PROP_0,
PROP_DEACTIVATED_ELEMENTS_STATE, PROP_ID,
PROP_LAST, PROP_LAST,
}; };
@ -201,6 +201,8 @@ struct _NleCompositionPrivate
NleUpdateStackReason updating_reason; NleUpdateStackReason updating_reason;
guint seek_seqnum; guint seek_seqnum;
gchar *id;
}; };
#define ACTION_CALLBACK(__action) (((GCClosure*) (__action))->callback) #define ACTION_CALLBACK(__action) (((GCClosure*) (__action))->callback)
@ -208,6 +210,7 @@ struct _NleCompositionPrivate
static guint _signals[LAST_SIGNAL] = { 0 }; static guint _signals[LAST_SIGNAL] = { 0 };
static GParamSpec *nleobject_properties[NLEOBJECT_PROP_LAST]; static GParamSpec *nleobject_properties[NLEOBJECT_PROP_LAST];
static GParamSpec *properties[PROP_LAST];
G_DEFINE_TYPE_WITH_CODE (NleComposition, nle_composition, NLE_TYPE_OBJECT, G_DEFINE_TYPE_WITH_CODE (NleComposition, nle_composition, NLE_TYPE_OBJECT,
G_ADD_PRIVATE (NleComposition) G_ADD_PRIVATE (NleComposition)
@ -970,6 +973,41 @@ drop:
return; return;
} }
static void
nle_composition_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
NleComposition *comp = (NleComposition *) object;
switch (property_id) {
case PROP_ID:
GST_OBJECT_LOCK (comp);
g_value_set_string (value, comp->priv->id);
GST_OBJECT_UNLOCK (comp);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (comp, property_id, pspec);
}
}
static void
nle_composition_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
NleComposition *comp = (NleComposition *) object;
switch (property_id) {
case PROP_ID:
GST_OBJECT_LOCK (comp);
g_free (comp->priv->id);
comp->priv->id = g_value_dup_string (value);
GST_OBJECT_UNLOCK (comp);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (comp, property_id, pspec);
}
}
static void static void
nle_composition_class_init (NleCompositionClass * klass) nle_composition_class_init (NleCompositionClass * klass)
{ {
@ -991,6 +1029,10 @@ nle_composition_class_init (NleCompositionClass * klass)
gobject_class->dispose = GST_DEBUG_FUNCPTR (nle_composition_dispose); gobject_class->dispose = GST_DEBUG_FUNCPTR (nle_composition_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (nle_composition_finalize); gobject_class->finalize = GST_DEBUG_FUNCPTR (nle_composition_finalize);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (nle_composition_get_property);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (nle_composition_set_property);
gstelement_class->change_state = nle_composition_change_state; gstelement_class->change_state = nle_composition_change_state;
@ -1012,6 +1054,11 @@ nle_composition_class_init (NleCompositionClass * klass)
nleobject_properties[NLEOBJECT_PROP_DURATION] = nleobject_properties[NLEOBJECT_PROP_DURATION] =
g_object_class_find_property (gobject_class, "duration"); g_object_class_find_property (gobject_class, "duration");
properties[PROP_ID] =
g_param_spec_string ("id", "Id", "The stream-id of the composition",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, properties);
_signals[COMMITED_SIGNAL] = _signals[COMMITED_SIGNAL] =
g_signal_new ("commited", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, g_signal_new ("commited", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
@ -1063,6 +1110,8 @@ nle_composition_init (NleComposition * comp)
nle_composition_reset (comp); nle_composition_reset (comp);
priv->id = gst_pad_create_stream_id (NLE_OBJECT_SRC (comp),
GST_ELEMENT (comp), NULL);
priv->nle_event_pad_func = GST_PAD_EVENTFUNC (NLE_OBJECT_SRC (comp)); priv->nle_event_pad_func = GST_PAD_EVENTFUNC (NLE_OBJECT_SRC (comp));
gst_pad_set_event_function (NLE_OBJECT_SRC (comp), gst_pad_set_event_function (NLE_OBJECT_SRC (comp),
GST_DEBUG_FUNCPTR (nle_composition_event_handler)); GST_DEBUG_FUNCPTR (nle_composition_event_handler));
@ -1141,6 +1190,7 @@ nle_composition_finalize (GObject * object)
g_mutex_clear (&priv->actions_lock); g_mutex_clear (&priv->actions_lock);
g_cond_clear (&priv->actions_cond); g_cond_clear (&priv->actions_cond);
g_free (priv->id);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -1273,8 +1323,10 @@ ghost_event_probe_handler (GstPad * ghostpad G_GNUC_UNUSED,
case GST_EVENT_STREAM_START: case GST_EVENT_STREAM_START:
if (g_atomic_int_compare_and_exchange (&priv->send_stream_start, TRUE, if (g_atomic_int_compare_and_exchange (&priv->send_stream_start, TRUE,
FALSE)) { FALSE)) {
/* FIXME: Do we want to create a new stream ID here? */
GST_DEBUG_OBJECT (comp, "forward stream-start %p", event); gst_event_unref (event);
event = info->data = gst_event_new_stream_start (g_strdup (priv->id));
GST_INFO_OBJECT (comp, "forward stream-start %p (%s)", event, priv->id);
} else { } else {
GST_DEBUG_OBJECT (comp, "dropping stream-start %p", event); GST_DEBUG_OBJECT (comp, "dropping stream-start %p", event);
retval = GST_PAD_PROBE_DROP; retval = GST_PAD_PROBE_DROP;