mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 17:51:16 +00:00
ges: Add support for sources reverse playback
It introduces a `reverse` property at the `nlesource` level which will basically reverse playback of the clip. We guarantee that outside that clip, the data flow looks like it was playing forward as we add an 'identity' element with `single-segment=true`. This start making use of the newly introduced concept of `CHILD_PROP_FLAG_SET_ON_ALL_INSTANCES` as it is natural that doing `source_clip.set_child_property("reverse", True)` will make the whole clip go reverse, meaning that all the GESSource children properties will be set. To set an individual source "reverse" child property as the desired effect. Fixes: https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/issues/24 Depends on: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/451 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/918>
This commit is contained in:
parent
526f00b07f
commit
a342d14ba9
13 changed files with 409 additions and 43 deletions
|
@ -265,7 +265,20 @@
|
||||||
"presence": "always"
|
"presence": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {
|
||||||
|
"reverse": {
|
||||||
|
"blurb": "Whether to playback the source reverse or not",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "false",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gboolean",
|
||||||
|
"writable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"rank": "none",
|
"rank": "none",
|
||||||
"signals": {}
|
"signals": {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -266,6 +266,36 @@ ges_source_get_rendering_smartly (GESSource * source)
|
||||||
return source->priv->is_rendering_smartly;
|
return source->priv->is_rendering_smartly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
ges_source_create_nle_object (GESTrackElement * self)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
GstElement *nleobject;
|
||||||
|
|
||||||
|
nleobject =
|
||||||
|
GES_TRACK_ELEMENT_CLASS (ges_source_parent_class)->create_gnl_object
|
||||||
|
(self);
|
||||||
|
|
||||||
|
if (!nleobject)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pspec =
|
||||||
|
g_object_class_find_property (G_OBJECT_GET_CLASS (nleobject), "reverse");
|
||||||
|
g_assert (pspec);
|
||||||
|
|
||||||
|
|
||||||
|
if (!ges_timeline_element_add_child_property_full (GES_TIMELINE_ELEMENT
|
||||||
|
(self), NULL, pspec, G_OBJECT (nleobject),
|
||||||
|
GES_TIMELINE_ELEMENT_CHILD_PROP_FLAG_SET_ON_ALL_INSTANCES))
|
||||||
|
GST_ERROR_OBJECT (self,
|
||||||
|
"Could not register the child property 'reverse' for %" GST_PTR_FORMAT,
|
||||||
|
nleobject);
|
||||||
|
|
||||||
|
g_param_spec_unref (pspec);
|
||||||
|
|
||||||
|
return nleobject;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ges_source_dispose (GObject * object)
|
ges_source_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -290,6 +320,7 @@ ges_source_class_init (GESSourceClass * klass)
|
||||||
|
|
||||||
track_class->nleobject_factorytype = "nlesource";
|
track_class->nleobject_factorytype = "nlesource";
|
||||||
track_class->create_element = NULL;
|
track_class->create_element = NULL;
|
||||||
|
track_class->create_gnl_object = ges_source_create_nle_object;
|
||||||
object_class->dispose = ges_source_dispose;
|
object_class->dispose = ges_source_dispose;
|
||||||
|
|
||||||
GES_TRACK_ELEMENT_CLASS_DEFAULT_HAS_INTERNAL_SOURCE (klass) = TRUE;
|
GES_TRACK_ELEMENT_CLASS_DEFAULT_HAS_INTERNAL_SOURCE (klass) = TRUE;
|
||||||
|
|
|
@ -408,17 +408,16 @@ ges_timeline_element_finalize (GObject * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_child_prop_spec (ChildPropSpec * childprop)
|
_child_prop_spec_free (ChildPropSpec * childprop)
|
||||||
{
|
{
|
||||||
g_object_freeze_notify (childprop->child);
|
g_object_freeze_notify (childprop->child);
|
||||||
if (childprop->handler_id)
|
if (childprop->handler_id)
|
||||||
g_signal_handler_disconnect (childprop->child, childprop->handler_id);
|
g_signal_handler_disconnect (childprop->child, childprop->handler_id);
|
||||||
g_object_thaw_notify (childprop->child);
|
g_object_thaw_notify (childprop->child);
|
||||||
|
|
||||||
if (handler->child != (GObject *) handler->self &&
|
if (childprop->child != (GObject *) childprop->self &&
|
||||||
handler->child != (GObject *) handler->owner)
|
childprop->child != (GObject *) childprop->owner)
|
||||||
gst_object_unref (handler->child);
|
gst_object_unref (childprop->child);
|
||||||
g_free (handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -439,7 +438,7 @@ ges_timeline_element_init (GESTimelineElement * self)
|
||||||
|
|
||||||
self->priv->children_props = g_array_new (TRUE, TRUE, sizeof (ChildPropSpec));
|
self->priv->children_props = g_array_new (TRUE, TRUE, sizeof (ChildPropSpec));
|
||||||
g_array_set_clear_func (self->priv->children_props,
|
g_array_set_clear_func (self->priv->children_props,
|
||||||
(GDestroyNotify) _child_prop_spec);
|
(GDestroyNotify) _child_prop_spec_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -809,7 +808,7 @@ child_prop_changed_cb (GObject * child, GParamSpec * arg,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
set_child_property (GESTimelineElement * self, ChildPropSpec * childprop,
|
set_child_property (GESTimelineElement * self, ChildPropSpec * childprop,
|
||||||
const GValue * value, GError **error)
|
const GValue * value, GError ** error)
|
||||||
{
|
{
|
||||||
GESTimelineElement *setter = self;
|
GESTimelineElement *setter = self;
|
||||||
GESTimelineElementClass *klass;
|
GESTimelineElementClass *klass;
|
||||||
|
@ -823,7 +822,7 @@ set_child_property (GESTimelineElement * self, ChildPropSpec * childprop,
|
||||||
|
|
||||||
if (klass->set_child_property_full)
|
if (klass->set_child_property_full)
|
||||||
return klass->set_child_property_full (setter, childprop->child,
|
return klass->set_child_property_full (setter, childprop->child,
|
||||||
childprop->pspec, value, error);
|
childprop->pspec, value, error);
|
||||||
|
|
||||||
g_assert (klass->set_child_property);
|
g_assert (klass->set_child_property);
|
||||||
klass->set_child_property (setter, childprop->child, childprop->pspec,
|
klass->set_child_property (setter, childprop->child, childprop->pspec,
|
||||||
|
@ -901,8 +900,7 @@ ges_timeline_element_add_child_property_full (GESTimelineElement * self,
|
||||||
child, pspec->name);
|
child, pspec->name);
|
||||||
|
|
||||||
signame = g_strconcat ("notify::", pspec->name, NULL);
|
signame = g_strconcat ("notify::", pspec->name, NULL);
|
||||||
handler = (ChildPropHandler *) g_new0 (ChildPropHandler, 1);
|
childprop.self = self;
|
||||||
handler->self = self;
|
|
||||||
if (child == G_OBJECT (self) || child == G_OBJECT (owner))
|
if (child == G_OBJECT (self) || child == G_OBJECT (owner))
|
||||||
childprop.child = child;
|
childprop.child = child;
|
||||||
else
|
else
|
||||||
|
@ -2321,12 +2319,12 @@ ges_timeline_element_remove_child_property_full (GESTimelineElement * self,
|
||||||
g_array_set_clear_func (self->priv->children_props, NULL);
|
g_array_set_clear_func (self->priv->children_props, NULL);
|
||||||
g_array_remove_index (self->priv->children_props, index);
|
g_array_remove_index (self->priv->children_props, index);
|
||||||
g_array_set_clear_func (self->priv->children_props,
|
g_array_set_clear_func (self->priv->children_props,
|
||||||
(GDestroyNotify) _child_prop_spec);
|
(GDestroyNotify) _child_prop_spec_free);
|
||||||
|
|
||||||
g_signal_emit (self, ges_timeline_element_signals[CHILD_PROPERTY_REMOVED], 0,
|
g_signal_emit (self, ges_timeline_element_signals[CHILD_PROPERTY_REMOVED], 0,
|
||||||
handler_copy.child, handler_copy.pspec);
|
handler_copy.child, handler_copy.pspec);
|
||||||
|
|
||||||
_child_prop_spec (&handler_copy);
|
_child_prop_spec_free (&handler_copy);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,12 @@ nle_object_translate_incoming_seek (NleObject * object, GstEvent * event)
|
||||||
if (G_UNLIKELY (format != GST_FORMAT_TIME))
|
if (G_UNLIKELY (format != GST_FORMAT_TIME))
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
|
|
||||||
|
|
||||||
|
if (NLE_IS_SOURCE (object) && NLE_SOURCE (object)->reverse) {
|
||||||
|
GST_DEBUG_OBJECT (object, "Reverse playback! %d", seqnum);
|
||||||
|
rate = -rate;
|
||||||
|
}
|
||||||
|
|
||||||
/* convert cur */
|
/* convert cur */
|
||||||
ncurtype = GST_SEEK_TYPE_SET;
|
ncurtype = GST_SEEK_TYPE_SET;
|
||||||
if (G_LIKELY ((curtype == GST_SEEK_TYPE_SET)
|
if (G_LIKELY ((curtype == GST_SEEK_TYPE_SET)
|
||||||
|
|
|
@ -38,12 +38,20 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS_ANY);
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_REVERSE,
|
||||||
|
PROP_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (nlesource);
|
GST_DEBUG_CATEGORY_STATIC (nlesource);
|
||||||
#define GST_CAT_DEFAULT nlesource
|
#define GST_CAT_DEFAULT nlesource
|
||||||
|
|
||||||
#define _do_init \
|
#define _do_init \
|
||||||
GST_DEBUG_CATEGORY_INIT (nlesource, "nlesource", GST_DEBUG_FG_BLUE | GST_DEBUG_BOLD, "GNonLin Source Element");
|
GST_DEBUG_CATEGORY_INIT (nlesource, "nlesource", GST_DEBUG_FG_BLUE | GST_DEBUG_BOLD, "GNonLin Source Element");
|
||||||
#define nle_source_parent_class parent_class
|
#define nle_source_parent_class parent_class
|
||||||
|
|
||||||
struct _NleSourcePrivate
|
struct _NleSourcePrivate
|
||||||
{
|
{
|
||||||
gboolean dispose_has_run;
|
gboolean dispose_has_run;
|
||||||
|
@ -62,6 +70,10 @@ struct _NleSourcePrivate
|
||||||
GstEvent *seek_event;
|
GstEvent *seek_event;
|
||||||
guint32 flush_seqnum;
|
guint32 flush_seqnum;
|
||||||
gulong probeid;
|
gulong probeid;
|
||||||
|
|
||||||
|
|
||||||
|
/* Identity automatically created to handle reverse playback */
|
||||||
|
GstElement *identity;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (NleSource, nle_source, NLE_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (NleSource, nle_source, NLE_TYPE_OBJECT,
|
||||||
|
@ -80,6 +92,57 @@ nle_source_control_element_func (NleSource * source, GstElement * element);
|
||||||
static GstStateChangeReturn nle_source_change_state (GstElement * element,
|
static GstStateChangeReturn nle_source_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
nle_source_commit (NleObject * object, gboolean recurse)
|
||||||
|
{
|
||||||
|
NleSource *self = NLE_SOURCE (object);
|
||||||
|
|
||||||
|
if (!NLE_OBJECT_CLASS (parent_class)->commit (object, recurse))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
self->reverse = self->pending_reverse;
|
||||||
|
g_object_set (self->priv->identity, "single-segment", self->reverse, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nle_source_get_property (GObject * object, guint property_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
NleSource *self = NLE_SOURCE (object);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_REVERSE:
|
||||||
|
g_value_set_boolean (value, self->pending_reverse);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nle_source_set_property (GObject * object, guint property_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
NleSource *self = NLE_SOURCE (object);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_REVERSE:
|
||||||
|
self->pending_reverse = g_value_get_boolean (value);
|
||||||
|
if (self->pending_reverse != self->reverse)
|
||||||
|
nle_object_set_commit_needed ((NleObject *) self);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nle_source_class_init (NleSourceClass * klass)
|
nle_source_class_init (NleSourceClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -93,6 +156,20 @@ nle_source_class_init (NleSourceClass * klass)
|
||||||
gstbin_class = (GstBinClass *) klass;
|
gstbin_class = (GstBinClass *) klass;
|
||||||
nleobject_class = (NleObjectClass *) klass;
|
nleobject_class = (NleObjectClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->get_property = nle_source_get_property;
|
||||||
|
gobject_class->set_property = nle_source_set_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NleSource:reverse:
|
||||||
|
* @reverse: Whether to playback the source reverse or not
|
||||||
|
*
|
||||||
|
* Since: 1.26
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_REVERSE,
|
||||||
|
g_param_spec_boolean ("reverse", "Reverse",
|
||||||
|
"Whether to playback the source reverse or not", FALSE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (gstelement_class, "GNonLin Source",
|
gst_element_class_set_static_metadata (gstelement_class, "GNonLin Source",
|
||||||
"Filter/Editor",
|
"Filter/Editor",
|
||||||
"Manages source elements",
|
"Manages source elements",
|
||||||
|
@ -106,6 +183,7 @@ nle_source_class_init (NleSourceClass * klass)
|
||||||
klass->control_element = GST_DEBUG_FUNCPTR (nle_source_control_element_func);
|
klass->control_element = GST_DEBUG_FUNCPTR (nle_source_control_element_func);
|
||||||
|
|
||||||
nleobject_class->prepare = GST_DEBUG_FUNCPTR (nle_source_prepare);
|
nleobject_class->prepare = GST_DEBUG_FUNCPTR (nle_source_prepare);
|
||||||
|
nleobject_class->commit = GST_DEBUG_FUNCPTR (nle_source_commit);
|
||||||
|
|
||||||
gstbin_class->add_element = GST_DEBUG_FUNCPTR (nle_source_add_element);
|
gstbin_class->add_element = GST_DEBUG_FUNCPTR (nle_source_add_element);
|
||||||
gstbin_class->remove_element = GST_DEBUG_FUNCPTR (nle_source_remove_element);
|
gstbin_class->remove_element = GST_DEBUG_FUNCPTR (nle_source_remove_element);
|
||||||
|
@ -139,10 +217,19 @@ srcpad_probe_cb (GstPad * pad, GstPadProbeInfo * info, NleSource * source)
|
||||||
static void
|
static void
|
||||||
nle_source_init (NleSource * source)
|
nle_source_init (NleSource * source)
|
||||||
{
|
{
|
||||||
|
NleSourcePrivate *priv;
|
||||||
|
NleObject *nleobject = NLE_OBJECT (source);
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (source, NLE_OBJECT_SOURCE);
|
GST_OBJECT_FLAG_SET (source, NLE_OBJECT_SOURCE);
|
||||||
source->element = NULL;
|
source->element = NULL;
|
||||||
source->priv = nle_source_get_instance_private (source);
|
priv = source->priv = nle_source_get_instance_private (source);
|
||||||
g_mutex_init (&source->priv->seek_lock);
|
priv->identity = gst_element_factory_make ("identity", NULL);
|
||||||
|
|
||||||
|
gst_bin_add (GST_BIN (source), priv->identity);
|
||||||
|
nle_object_ghost_pad_set_target (nleobject, nleobject->srcpad,
|
||||||
|
priv->identity->srcpads->data);
|
||||||
|
|
||||||
|
g_mutex_init (&priv->seek_lock);
|
||||||
|
|
||||||
gst_pad_add_probe (NLE_OBJECT_SRC (source),
|
gst_pad_add_probe (NLE_OBJECT_SRC (source),
|
||||||
GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, (GstPadProbeCallback) srcpad_probe_cb,
|
GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, (GstPadProbeCallback) srcpad_probe_cb,
|
||||||
|
@ -158,6 +245,8 @@ nle_source_dispose (GObject * object)
|
||||||
NleObject *nleobject = (NleObject *) object;
|
NleObject *nleobject = (NleObject *) object;
|
||||||
NleSource *source = (NleSource *) object;
|
NleSource *source = (NleSource *) object;
|
||||||
NleSourcePrivate *priv = source->priv;
|
NleSourcePrivate *priv = source->priv;
|
||||||
|
GstElement *tmpidentity;
|
||||||
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (object, "dispose");
|
GST_DEBUG_OBJECT (object, "dispose");
|
||||||
|
|
||||||
|
@ -173,26 +262,18 @@ nle_source_dispose (GObject * object)
|
||||||
}
|
}
|
||||||
GST_OBJECT_UNLOCK (object);
|
GST_OBJECT_UNLOCK (object);
|
||||||
|
|
||||||
|
gst_clear_object (&source->element);
|
||||||
if (source->element) {
|
tmpidentity = priv->identity;
|
||||||
gst_object_unref (source->element);
|
priv->identity = NULL;
|
||||||
source->element = NULL;
|
gst_bin_remove (GST_BIN (source), tmpidentity);
|
||||||
}
|
|
||||||
|
|
||||||
priv->dispose_has_run = TRUE;
|
priv->dispose_has_run = TRUE;
|
||||||
if (priv->ghostedpad)
|
nle_object_ghost_pad_set_target (nleobject, nleobject->srcpad, NULL);
|
||||||
nle_object_ghost_pad_set_target (nleobject, nleobject->srcpad, NULL);
|
|
||||||
|
|
||||||
if (priv->staticpad) {
|
gst_clear_object (&priv->staticpad);
|
||||||
gst_object_unref (priv->staticpad);
|
|
||||||
priv->staticpad = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_mutex_lock (&priv->seek_lock);
|
g_mutex_lock (&priv->seek_lock);
|
||||||
if (priv->seek_event) {
|
gst_clear_event (&priv->seek_event);
|
||||||
gst_event_unref (priv->seek_event);
|
|
||||||
priv->seek_event = NULL;
|
|
||||||
}
|
|
||||||
g_mutex_unlock (&priv->seek_lock);
|
g_mutex_unlock (&priv->seek_lock);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
@ -225,12 +306,14 @@ element_pad_added_cb (GstElement * element G_GNUC_UNUSED, GstPad * pad,
|
||||||
}
|
}
|
||||||
gst_caps_unref (srccaps);
|
gst_caps_unref (srccaps);
|
||||||
|
|
||||||
priv->ghostedpad = pad;
|
if (gst_pad_link (pad, priv->identity->sinkpads->data) != GST_PAD_LINK_OK) {
|
||||||
GST_DEBUG_OBJECT (nleobject, "SET target %" GST_PTR_FORMAT, pad);
|
GST_ERROR_OBJECT (source, "Could not link pads: %" GST_PTR_FORMAT
|
||||||
nle_object_ghost_pad_set_target (nleobject, nleobject->srcpad, pad);
|
" and %" GST_PTR_FORMAT, pad, priv->identity->sinkpads->data);
|
||||||
|
} else {
|
||||||
GST_DEBUG_OBJECT (source, "Using pad pad %s:%s as a target now!",
|
GST_DEBUG_OBJECT (source, "Linked pads: %" GST_PTR_FORMAT
|
||||||
GST_DEBUG_PAD_NAME (pad));
|
" and %" GST_PTR_FORMAT, pad, priv->identity->sinkpads->data);
|
||||||
|
priv->ghostedpad = pad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -238,7 +321,6 @@ element_pad_removed_cb (GstElement * element G_GNUC_UNUSED, GstPad * pad,
|
||||||
NleSource * source)
|
NleSource * source)
|
||||||
{
|
{
|
||||||
NleSourcePrivate *priv = source->priv;
|
NleSourcePrivate *priv = source->priv;
|
||||||
NleObject *nleobject = (NleObject *) source;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (source, "pad %s:%s (controlled pad %s:%s)",
|
GST_DEBUG_OBJECT (source, "pad %s:%s (controlled pad %s:%s)",
|
||||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (priv->ghostedpad));
|
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (priv->ghostedpad));
|
||||||
|
@ -249,9 +331,9 @@ element_pad_removed_cb (GstElement * element G_GNUC_UNUSED, GstPad * pad,
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (source, "Clearing up ghostpad");
|
GST_DEBUG_OBJECT (source, "Clearing up ghostpad");
|
||||||
|
|
||||||
if (nleobject->srcpad)
|
if (priv->identity && !gst_pad_unlink (pad, priv->identity->sinkpads->data))
|
||||||
nle_object_ghost_pad_set_target (NLE_OBJECT (source), nleobject->srcpad,
|
GST_ERROR_OBJECT (source, "Could not unlink pads: %" GST_PTR_FORMAT
|
||||||
NULL);
|
" and %" GST_PTR_FORMAT, pad, priv->identity->sinkpads->data);
|
||||||
priv->ghostedpad = NULL;
|
priv->ghostedpad = NULL;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (source, "The removed pad is NOT our controlled pad");
|
GST_DEBUG_OBJECT (source, "The removed pad is NOT our controlled pad");
|
||||||
|
@ -343,6 +425,9 @@ nle_source_control_element_func (NleSource * source, GstElement * element)
|
||||||
NleSourcePrivate *priv = source->priv;
|
NleSourcePrivate *priv = source->priv;
|
||||||
GstPad *pad = NULL;
|
GstPad *pad = NULL;
|
||||||
|
|
||||||
|
if (element == priv->identity)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (source->element == NULL, FALSE);
|
g_return_val_if_fail (source->element == NULL, FALSE);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (source, "element: %" GST_PTR_FORMAT ", source->element:%"
|
GST_DEBUG_OBJECT (source, "element: %" GST_PTR_FORMAT ", source->element:%"
|
||||||
|
@ -353,8 +438,13 @@ nle_source_control_element_func (NleSource * source, GstElement * element)
|
||||||
|
|
||||||
if (get_valid_src_pad (source, source->element, &pad)) {
|
if (get_valid_src_pad (source, source->element, &pad)) {
|
||||||
priv->staticpad = pad;
|
priv->staticpad = pad;
|
||||||
nle_object_ghost_pad_set_target (NLE_OBJECT (source),
|
if (gst_pad_link (pad, priv->identity->sinkpads->data) != GST_PAD_LINK_OK) {
|
||||||
NLE_OBJECT_SRC (source), pad);
|
GST_ERROR_OBJECT (source, "Could not link pads: %" GST_PTR_FORMAT
|
||||||
|
" and %" GST_PTR_FORMAT, pad, priv->identity->sinkpads->data);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (source, "Linked pads: %" GST_PTR_FORMAT
|
||||||
|
" and %" GST_PTR_FORMAT, pad, priv->identity->sinkpads->data);
|
||||||
|
}
|
||||||
priv->dynamicpads = FALSE;
|
priv->dynamicpads = FALSE;
|
||||||
} else {
|
} else {
|
||||||
priv->dynamicpads = has_dynamic_srcpads (element);
|
priv->dynamicpads = has_dynamic_srcpads (element);
|
||||||
|
@ -544,7 +634,8 @@ nle_source_prepare (NleObject * object)
|
||||||
stop = object->inpoint + object->duration;
|
stop = object->inpoint + object->duration;
|
||||||
|
|
||||||
g_mutex_lock (&source->priv->seek_lock);
|
g_mutex_lock (&source->priv->seek_lock);
|
||||||
source->priv->seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
|
source->priv->seek_event = gst_event_new_seek (source->reverse ? -1.0 : 1.0,
|
||||||
|
GST_FORMAT_TIME,
|
||||||
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
|
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
|
||||||
GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop);
|
GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop);
|
||||||
g_mutex_unlock (&source->priv->seek_lock);
|
g_mutex_unlock (&source->priv->seek_lock);
|
||||||
|
|
|
@ -45,6 +45,8 @@ typedef struct _NleSourcePrivate NleSourcePrivate;
|
||||||
struct _NleSource
|
struct _NleSource
|
||||||
{
|
{
|
||||||
NleObject parent;
|
NleObject parent;
|
||||||
|
gboolean reverse;
|
||||||
|
gboolean pending_reverse;
|
||||||
|
|
||||||
/* controlled source element, acces with gst_bin_[add|remove]_element */
|
/* controlled source element, acces with gst_bin_[add|remove]_element */
|
||||||
GstElement *element;
|
GstElement *element;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
meta,
|
||||||
|
tool = "ges-launch-$(gst_api_version)",
|
||||||
|
args = {
|
||||||
|
--videosink, "fakevideosink name=videosink qos=false",
|
||||||
|
--audiosink, "fakeaudiosink name=audiosink qos=false",
|
||||||
|
--video-caps, "video/x-raw,width=1280,height=720,framerate=30/1,format=I420",
|
||||||
|
--audio-caps, "audio/x-raw,rate=44100,format=S32LE,channels=2,layout=interleaved",
|
||||||
|
},
|
||||||
|
handles-states = true,
|
||||||
|
ignore-eos = true,
|
||||||
|
configs = {
|
||||||
|
# We can't record buffers on sources as we have no timing guarantees
|
||||||
|
"$(validateflow), pad=videosrcbin:src, ignored-fields=\"stream-start={stream-id, group-id, stream}\"",
|
||||||
|
"$(validateflow), pad=videosink:sink, record-buffers=true, ignored-fields=\"stream-start={stream-id, group-id, stream}\"",
|
||||||
|
"$(validateflow), pad=audiosrcbin:src, ignored-fields=\"stream-start={stream-id, group-id, stream}\"",
|
||||||
|
"$(validateflow), pad=audiosink:sink, record-buffers=true, ignored-fields=\"stream-start={stream-id, group-id, stream}\"",
|
||||||
|
}
|
||||||
|
|
||||||
|
add-clip, name=c0, asset-id="time-overlay,disable-timecodestamper=true", layer-priority=0, type=GESTestClip, start=0, duration=1.0
|
||||||
|
set-child-properties, element-name=c0, pattern=blue, valignment=center, halignment=center, reverse=true
|
||||||
|
play
|
||||||
|
|
||||||
|
pause, on-message=eos
|
||||||
|
check-position, expected-position=1000000001
|
||||||
|
stop
|
|
@ -0,0 +1,107 @@
|
||||||
|
event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE;
|
||||||
|
event caps: audio/x-raw, channel-mask=(bitmask)0x0000000000000003, channels=(int)2, format=(string)S32LE, layout=(string)interleaved, rate=(int)44100;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000
|
||||||
|
buffer: pts=0:00:00.000000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.010000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.020000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.030000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.040000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.050000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.060000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.070000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.080000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.090000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.100000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.110000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.120000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.130000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.140000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.150000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.160000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.170000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.180000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.190000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.200000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.210000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.220000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.230000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.240000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.250000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.260000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.270000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.280000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.290000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.300000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.310000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.320000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.330000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.340000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.350000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.360000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.370000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.380000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.390000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.400000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.410000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.420000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.430000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.440000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.450000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.460000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.470000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.480000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.490000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.500000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.510000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.520000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.530000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.540000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.550000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.560000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.570000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.580000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.590000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.600000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.610000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.620000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.630000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.640000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.650000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.660000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.670000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.680000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.690000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.700000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.710000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.720000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.730000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.740000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.750000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.760000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.770000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.780000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.790000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.800000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.810000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.820000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.830000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.840000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.850000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.860000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.870000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.880000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.890000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.900000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.910000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.920000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.930000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.940000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.950000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.960000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.970000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.980000000, dur=0:00:00.010000000
|
||||||
|
buffer: pts=0:00:00.990000000, dur=0:00:00.010000000
|
||||||
|
event segment: format=TIME, start=0:00:01.000000000, offset=0:00:00.000000000, stop=0:00:01.000000001, flags=0x01, time=0:00:01.000000000, base=0:00:01.000000000, position=0:00:01.000000000
|
||||||
|
buffer: pts=0:00:01.000000000, dur=0:00:00.000000001, flags=gap
|
||||||
|
event gap: GstEventGap, duration=(guint64)18446744073709551615, timestamp=(guint64)1000022675;
|
||||||
|
event eos: (no structure)
|
|
@ -0,0 +1,8 @@
|
||||||
|
event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE;
|
||||||
|
event caps: audio/x-raw, channel-mask=(bitmask)0x0000000000000003, channels=(int)2, format=(string)S32LE, layout=(string)interleaved, rate=(int)44100;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000
|
||||||
|
event tag: GstTagList-stream, taglist=(taglist)"taglist\,\ description\=\(string\)\"audiotest\\\ wave\"\;";
|
||||||
|
event flush-start: (no structure)
|
||||||
|
event flush-stop: GstEventFlushStop, reset-time=(boolean)true;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, rate=-1.000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:01.000000000
|
||||||
|
event eos: (no structure)
|
|
@ -0,0 +1,37 @@
|
||||||
|
event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE;
|
||||||
|
event caps: video/x-raw, colorimetry=(string)bt709, format=(string)I420, framerate=(fraction)30/1, height=(int)720, width=(int)1280;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=none
|
||||||
|
buffer: pts=0:00:00.000000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.033333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.066666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.100000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.133333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.166666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.200000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.233333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.266666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.300000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.333333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.366666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.400000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.433333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.466666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.500000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.533333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.566666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.600000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.633333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.666666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.700000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.733333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.766666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.800000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.833333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.866666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.900000000, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.933333333, dur=0:00:00.033333333, meta=GstVideoMeta
|
||||||
|
buffer: pts=0:00:00.966666666, dur=0:00:00.033333334, meta=GstVideoMeta
|
||||||
|
event caps: video/x-raw, colorimetry=(string)bt601, format=(string)I420, framerate=(fraction)30/1, height=(int)720, width=(int)1280;
|
||||||
|
event segment: format=TIME, start=0:00:01.000000000, offset=0:00:00.000000000, stop=0:00:01.000000001, flags=0x01, time=0:00:01.000000000, base=0:00:01.000000000, position=none
|
||||||
|
buffer: pts=0:00:01.000000000, dur=0:00:00.000000001, meta=GstVideoMeta
|
||||||
|
event eos: (no structure)
|
|
@ -0,0 +1,7 @@
|
||||||
|
event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE;
|
||||||
|
event caps: video/x-raw, format=(string)AYUV, framerate=(fraction)30/1, height=(int)720, interlace-mode=(string)progressive, multiview-mode=(string)mono, pixel-aspect-ratio=(fraction)1/1, width=(int)1280;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000
|
||||||
|
event flush-start: (no structure)
|
||||||
|
event flush-stop: GstEventFlushStop, reset-time=(boolean)true;
|
||||||
|
event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, rate=-1.000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:01.000000000
|
||||||
|
event eos: (no structure)
|
|
@ -0,0 +1,39 @@
|
||||||
|
meta,
|
||||||
|
tool = "ges-launch-$(gst_api_version)",
|
||||||
|
handles-states = true
|
||||||
|
|
||||||
|
add-clip, name=c0, asset-id="time-overlay", layer-priority=0, type=GESTestClip, start=0, duration=1.0
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=false
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=false
|
||||||
|
|
||||||
|
set-child-properties, element-name=c0, pattern=blue, valignment=center, halignment=center, reverse=true
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=true
|
||||||
|
|
||||||
|
set-child-properties, element-name=videotestsource0, reverse=false
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=false
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=true
|
||||||
|
|
||||||
|
|
||||||
|
add-clip, name=c1, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=1.0, duration=2.0
|
||||||
|
group, containers={c0, c1}, container-name=g0
|
||||||
|
|
||||||
|
set-child-properties, element-name=g0, reverse=true
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=videotestsource1, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource1, reverse=true
|
||||||
|
|
||||||
|
set-child-properties, element-name=audiotestsource1, reverse=false
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=videotestsource1, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource1, reverse=false
|
||||||
|
|
||||||
|
ungroup-container, container-name=g0
|
||||||
|
check-child-properties, element-name=videotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource0, reverse=true
|
||||||
|
check-child-properties, element-name=videotestsource1, reverse=true
|
||||||
|
check-child-properties, element-name=audiotestsource1, reverse=false
|
||||||
|
|
||||||
|
stop
|
|
@ -762,3 +762,5 @@ ges.test.play_two_nested_back_to_back
|
||||||
ges.test.seek_on_stack_change_on_internal_subtimeline
|
ges.test.seek_on_stack_change_on_internal_subtimeline
|
||||||
ges.test.videoscale_effect
|
ges.test.videoscale_effect
|
||||||
ges.test.backward_playback_with_start
|
ges.test.backward_playback_with_start
|
||||||
|
ges.test.check_reverse_source
|
||||||
|
ges.test.timelineelement.set_child_prop_on_all_instances
|
||||||
|
|
Loading…
Reference in a new issue