diff --git a/docs/gst_plugins_cache.json b/docs/gst_plugins_cache.json index 938f8b564b..717f7ffed7 100644 --- a/docs/gst_plugins_cache.json +++ b/docs/gst_plugins_cache.json @@ -8,6 +8,7 @@ "description": "Demuxer for complex timeline file formats using GES.", "hierarchy": [ "GESDemux", + "GESBaseBin", "GstBin", "GstElement", "GstObject", @@ -51,11 +52,11 @@ "writable": true }, "timeline": { - "blurb": "Timeline to use in this source.", + "blurb": "Timeline to use in this src.", "construct": false, "construct-only": false, "type-name": "GESTimeline", - "writable": false + "writable": true } }, "rank": "primary", @@ -79,18 +80,19 @@ } }, "gessrc": { - "author": "Erik Walthinsen ,Wim Taymans ", - "description": "Simple container object", + "author": "Thibault Saunier + * + * gesbasebin.h + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "gesbasebin.h" + +static GstStaticPadTemplate video_src_template = +GST_STATIC_PAD_TEMPLATE ("video_src", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("video/x-raw(ANY)")); + +static GstStaticPadTemplate audio_src_template = + GST_STATIC_PAD_TEMPLATE ("audio_src", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("audio/x-raw(ANY);")); + +typedef struct +{ + GESTimeline *timeline; + GstFlowCombiner *flow_combiner; +} GESBaseBinPrivate; + +enum +{ + PROP_0, + PROP_TIMELINE, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +G_DEFINE_TYPE_WITH_PRIVATE (GESBaseBin, ges_base_bin, GST_TYPE_BIN); + +GST_DEBUG_CATEGORY_STATIC (gesbasebin); +#define GST_CAT_DEFAULT gesbasebin + +static void +ges_base_bin_dispose (GObject * object) +{ + GESBaseBin *self = GES_BASE_BIN (object); + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + if (priv->timeline) + gst_clear_object (&priv->timeline); +} + +static void +ges_base_bin_finalize (GObject * object) +{ + GESBaseBin *self = GES_BASE_BIN (object); + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + gst_flow_combiner_free (priv->flow_combiner); +} + +static void +ges_base_bin_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GESBaseBin *self = GES_BASE_BIN (object); + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + switch (property_id) { + case PROP_TIMELINE: + g_value_set_object (value, priv->timeline); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +ges_base_bin_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GESBaseBin *self = GES_BASE_BIN (object); + + switch (property_id) { + case PROP_TIMELINE: + ges_base_bin_set_timeline (self, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +ges_base_bin_class_init (GESBaseBinClass * self_class) +{ + GObjectClass *gclass = G_OBJECT_CLASS (self_class); + GstElementClass *gstelement_klass = GST_ELEMENT_CLASS (self_class); + + GST_DEBUG_CATEGORY_INIT (gesbasebin, "gesbasebin", 0, "ges bin element"); + + gclass->get_property = ges_base_bin_get_property; + gclass->set_property = ges_base_bin_set_property; + gclass->dispose = ges_base_bin_dispose; + gclass->finalize = ges_base_bin_finalize; + + /** + * GESBaseBin:timeline: + * + * Timeline to use in this bin. + */ + properties[PROP_TIMELINE] = g_param_spec_object ("timeline", "Timeline", + "Timeline to use in this src.", + GES_TYPE_TIMELINE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gclass, PROP_LAST, properties); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&video_src_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&audio_src_template)); +} + +static void +ges_base_bin_init (GESBaseBin * self) +{ + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + priv->flow_combiner = gst_flow_combiner_new (); +} + +static GstFlowReturn +gst_bin_src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstFlowReturn result, chain_result; + GESBaseBin *self = GES_BASE_BIN (GST_OBJECT_PARENT (parent)); + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + chain_result = gst_proxy_pad_chain_default (pad, GST_OBJECT (self), buffer); + result = + gst_flow_combiner_update_pad_flow (priv->flow_combiner, pad, + chain_result); + + if (result == GST_FLOW_FLUSHING) + return chain_result; + + return result; +} + + +gboolean +ges_base_bin_set_timeline (GESBaseBin * self, GESTimeline * timeline) +{ + GList *tmp; + guint naudiopad = 0, nvideopad = 0; + GstBin *sbin = GST_BIN (self); + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE); + + if (priv->timeline) { + GST_ERROR_OBJECT (sbin, "Implement changing timeline support"); + + return FALSE; + } + + priv->timeline = gst_object_ref (timeline); + GST_INFO_OBJECT (sbin, "Setting timeline: %" GST_PTR_FORMAT, timeline); + if (!gst_bin_add (sbin, GST_ELEMENT (timeline))) { + GST_ERROR_OBJECT (sbin, "Could not add timeline to myself!"); + + return FALSE; + } + + for (tmp = timeline->tracks; tmp; tmp = tmp->next) { + GstPad *gpad; + gchar *name = NULL; + GstElement *queue; + GESTrack *track = GES_TRACK (tmp->data); + GstPad *proxy_pad, *tmppad, *pad = + ges_timeline_get_pad_for_track (timeline, track); + GstStaticPadTemplate *template; + + if (!pad) { + GST_WARNING_OBJECT (sbin, "No pad for track: %" GST_PTR_FORMAT, track); + + continue; + } + + if (track->type == GES_TRACK_TYPE_AUDIO) { + name = g_strdup_printf ("audio_%u", naudiopad++); + template = &audio_src_template; + } else if (track->type == GES_TRACK_TYPE_VIDEO) { + name = g_strdup_printf ("video_%u", nvideopad++); + template = &video_src_template; + } else { + GST_INFO_OBJECT (sbin, "Track type not handled: %" GST_PTR_FORMAT, track); + continue; + } + + queue = gst_element_factory_make ("queue", NULL); + /* Add queues the same way as in GESPipeline */ + g_object_set (G_OBJECT (queue), "max-size-buffers", 0, + "max-size-bytes", 0, "max-size-time", (gint64) 2 * GST_SECOND, NULL); + gst_bin_add (sbin, queue); + gst_element_sync_state_with_parent (GST_ELEMENT (queue)); + + tmppad = gst_element_get_static_pad (queue, "sink"); + if (gst_pad_link (pad, tmppad) != GST_PAD_LINK_OK) { + GST_ERROR_OBJECT (sbin, "Could not link %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (tmppad)); + + gst_object_unref (tmppad); + gst_object_unref (queue); + continue; + } + + tmppad = gst_element_get_static_pad (queue, "src"); + gpad = gst_ghost_pad_new_from_template (name, tmppad, + gst_static_pad_template_get (template)); + + gst_pad_set_active (gpad, TRUE); + gst_element_add_pad (GST_ELEMENT (sbin), gpad); + + proxy_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad))); + gst_flow_combiner_add_pad (priv->flow_combiner, proxy_pad); + gst_pad_set_chain_function (proxy_pad, gst_bin_src_chain); + gst_object_unref (proxy_pad); + GST_DEBUG_OBJECT (sbin, "Adding pad: %" GST_PTR_FORMAT, gpad); + } + + gst_element_no_more_pads (GST_ELEMENT (sbin)); + gst_element_sync_state_with_parent (GST_ELEMENT (timeline)); + + return TRUE; +} + +GESTimeline * +ges_base_bin_get_timeline (GESBaseBin * self) +{ + GESBaseBinPrivate *priv = ges_base_bin_get_instance_private (self); + + return priv->timeline; +} diff --git a/plugins/ges/gesbasebin.h b/plugins/ges/gesbasebin.h new file mode 100644 index 0000000000..a48adb4bd1 --- /dev/null +++ b/plugins/ges/gesbasebin.h @@ -0,0 +1,44 @@ +/* GStreamer GES plugin + * + * Copyright (C) 2019 Thibault Saunier + * + * gesbasebin.h + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef __GES_BASE_BIN_H__ +#define __GES_BASE_BIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +G_DECLARE_DERIVABLE_TYPE(GESBaseBin, ges_base_bin, GES, BASE_BIN, GstBin) + +struct _GESBaseBinClass +{ + GstBinClass parent_class; +}; + +gboolean ges_base_bin_set_timeline (GESBaseBin * self, GESTimeline * timeline); +GESTimeline * ges_base_bin_get_timeline (GESBaseBin * self); + +G_END_DECLS +#endif /* __GES_BASE_BIN_H__ */ \ No newline at end of file diff --git a/plugins/ges/gesdemux.c b/plugins/ges/gesdemux.c index ca9f49ed5e..62ff2c0398 100644 --- a/plugins/ges/gesdemux.c +++ b/plugins/ges/gesdemux.c @@ -36,47 +36,35 @@ #include "config.h" #endif +#include "gesbasebin.h" + #include #include #include #include #include -#include GST_DEBUG_CATEGORY_STATIC (gesdemux); #define GST_CAT_DEFAULT gesdemux -static GstStaticPadTemplate video_src_template = -GST_STATIC_PAD_TEMPLATE ("video_src", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("video/x-raw(ANY)")); - -static GstStaticPadTemplate audio_src_template = - GST_STATIC_PAD_TEMPLATE ("audio_src", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("audio/x-raw(ANY);")); - static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/xges")); -G_DECLARE_FINAL_TYPE (GESDemux, ges_demux, GES, Demux, GstBin); +G_DECLARE_FINAL_TYPE (GESDemux, ges_demux, GES, Demux, GESBaseBin); struct _GESDemux { - GstBin parent; + GESBaseBin parent; GESTimeline *timeline; GstPad *sinkpad; GstAdapter *input_adapter; - GstFlowCombiner *flow_combiner; }; -G_DEFINE_TYPE (GESDemux, ges_demux, GST_TYPE_BIN); +G_DEFINE_TYPE (GESDemux, ges_demux, ges_base_bin_get_type ()); #define GES_DEMUX(obj) ((GESDemux*)obj) enum @@ -88,112 +76,6 @@ enum static GParamSpec *properties[PROP_LAST]; -static GstFlowReturn -gst_demux_src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) -{ - GstFlowReturn result, chain_result; - GESDemux *self = GES_DEMUX (GST_OBJECT_PARENT (parent)); - - chain_result = gst_proxy_pad_chain_default (pad, GST_OBJECT (self), buffer); - result = - gst_flow_combiner_update_pad_flow (self->flow_combiner, pad, - chain_result); - - if (result == GST_FLOW_FLUSHING) { - return chain_result; - } - - return result; -} - -static gboolean -ges_demux_set_timeline (GESDemux * self, GESTimeline * timeline) -{ - GList *tmp; - guint naudiopad = 0, nvideopad = 0; - GstBin *sbin = GST_BIN (self); - - g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE); - - if (self->timeline) { - GST_ERROR_OBJECT (self, "Implement changing timeline support"); - - return FALSE; - } - - GST_INFO_OBJECT (self, "Setting timeline: %" GST_PTR_FORMAT, timeline); - self->timeline = gst_object_ref (timeline); - - if (!gst_bin_add (sbin, GST_ELEMENT (self->timeline))) { - GST_ERROR_OBJECT (self, "Could not add timeline to myself!"); - - return FALSE; - } - - for (tmp = self->timeline->tracks; tmp; tmp = tmp->next) { - GstPad *gpad; - gchar *name = NULL; - GstElement *queue; - GESTrack *track = GES_TRACK (tmp->data); - GstPad *proxy_pad, *tmppad, *pad = - ges_timeline_get_pad_for_track (self->timeline, track); - GstStaticPadTemplate *template; - - if (!pad) { - GST_WARNING_OBJECT (self, "No pad for track: %" GST_PTR_FORMAT, track); - - continue; - } - - if (track->type == GES_TRACK_TYPE_AUDIO) { - name = g_strdup_printf ("audio_%u", naudiopad++); - template = &audio_src_template; - } else if (track->type == GES_TRACK_TYPE_VIDEO) { - name = g_strdup_printf ("video_%u", nvideopad++); - template = &video_src_template; - } else { - GST_INFO_OBJECT (self, "Track type not handled: %" GST_PTR_FORMAT, track); - continue; - } - - queue = gst_element_factory_make ("queue", NULL); - /* Add queues the same way as in GESPipeline */ - g_object_set (G_OBJECT (queue), "max-size-buffers", 0, - "max-size-bytes", 0, "max-size-time", (gint64) 2 * GST_SECOND, NULL); - gst_bin_add (GST_BIN (self), queue); - gst_element_sync_state_with_parent (GST_ELEMENT (queue)); - - tmppad = gst_element_get_static_pad (queue, "sink"); - if (gst_pad_link (pad, tmppad) != GST_PAD_LINK_OK) { - GST_ERROR_OBJECT (self, "Could not link %s:%s and %s:%s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (tmppad)); - - gst_object_unref (tmppad); - gst_object_unref (queue); - continue; - } - - tmppad = gst_element_get_static_pad (queue, "src"); - gpad = gst_ghost_pad_new_from_template (name, tmppad, - gst_static_pad_template_get (template)); - - gst_pad_set_active (gpad, TRUE); - gst_element_add_pad (GST_ELEMENT (self), gpad); - - proxy_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad))); - gst_flow_combiner_add_pad (self->flow_combiner, proxy_pad); - gst_pad_set_chain_function (proxy_pad, - (GstPadChainFunction) gst_demux_src_chain); - gst_object_unref (proxy_pad); - GST_DEBUG_OBJECT (self, "Adding pad: %" GST_PTR_FORMAT, gpad); - } - - gst_element_sync_state_with_parent (GST_ELEMENT (self->timeline)); - gst_element_no_more_pads (GST_ELEMENT (self)); - - return TRUE; -} - static void ges_demux_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) @@ -202,7 +84,8 @@ ges_demux_get_property (GObject * object, guint property_id, switch (property_id) { case PROP_TIMELINE: - g_value_set_object (value, self->timeline); + g_value_set_object (value, + ges_base_bin_get_timeline (GES_BASE_BIN (self))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -219,23 +102,6 @@ ges_demux_set_property (GObject * object, guint property_id, } } -static void -ges_demux_dispose (GObject * object) -{ - GESDemux *self = GES_DEMUX (object); - - if (self->timeline) - gst_clear_object (&self->timeline); -} - -static void -ges_demux_finalize (GObject * object) -{ - GESDemux *self = GES_DEMUX (object); - - gst_flow_combiner_free (self->flow_combiner); -} - static void ges_demux_class_init (GESDemuxClass * self_class) { @@ -246,8 +112,6 @@ ges_demux_class_init (GESDemuxClass * self_class) gclass->get_property = ges_demux_get_property; gclass->set_property = ges_demux_set_property; - gclass->dispose = ges_demux_dispose; - gclass->finalize = ges_demux_finalize; /** * GESDemux:timeline: @@ -257,21 +121,15 @@ ges_demux_class_init (GESDemuxClass * self_class) properties[PROP_TIMELINE] = g_param_spec_object ("timeline", "Timeline", "Timeline to use in this source.", GES_TYPE_TIMELINE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_override_property (gclass, PROP_TIMELINE, "timeline"); - g_object_class_install_properties (gclass, PROP_LAST, properties); - + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&sink_template)); gst_element_class_set_static_metadata (gstelement_klass, "GStreamer Editing Services based 'demuxer'", "Codec/Demux/Editing", "Demuxer for complex timeline file formats using GES.", "Thibault Saunier sinkpad); self->input_adapter = gst_adapter_new (); - self->flow_combiner = gst_flow_combiner_new (); gst_pad_set_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (ges_demux_sink_chain)); diff --git a/plugins/ges/gessrc.c b/plugins/ges/gessrc.c index 29dc897031..2eb574d258 100644 --- a/plugins/ges/gessrc.c +++ b/plugins/ges/gessrc.c @@ -48,112 +48,18 @@ #include #include +#include "gesbasebin.h" + GST_DEBUG_CATEGORY_STATIC (gessrc); #define GST_CAT_DEFAULT gessrc -static GstStaticPadTemplate video_src_template = -GST_STATIC_PAD_TEMPLATE ("video_src", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("video/x-raw(ANY)")); - -static GstStaticPadTemplate audio_src_template = - GST_STATIC_PAD_TEMPLATE ("audio_src", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("audio/x-raw(ANY);")); - -G_DECLARE_FINAL_TYPE (GESSrc, ges_src, GES, SRC, GstBin); +G_DECLARE_FINAL_TYPE (GESSrc, ges_src, GES, SRC, GESBaseBin); struct _GESSrc { - GstBin parent; - - GESTimeline *timeline; + GESBaseBin parent; }; #define GES_SRC(obj) ((GESSrc*) obj) -enum -{ - PROP_0, - PROP_TIMELINE, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - -static gboolean -ges_src_set_timeline (GESSrc * self, GESTimeline * timeline) -{ - GList *tmp; - guint naudiopad = 0, nvideopad = 0; - GstBin *sbin = GST_BIN (self); - - g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE); - - if (self->timeline) { - GST_FIXME_OBJECT (self, "Implement changing timeline support"); - - return FALSE; - } - - self->timeline = timeline; - - gst_bin_add (sbin, GST_ELEMENT (self->timeline)); - for (tmp = self->timeline->tracks; tmp; tmp = tmp->next) { - GstPad *gpad; - gchar *name = NULL; - GstElement *queue; - GESTrack *track = GES_TRACK (tmp->data); - GstPad *tmppad, *pad = - ges_timeline_get_pad_for_track (self->timeline, track); - GstStaticPadTemplate *template; - - if (!pad) { - GST_INFO_OBJECT (self, "No pad for track: %" GST_PTR_FORMAT, track); - - continue; - } - - if (track->type == GES_TRACK_TYPE_AUDIO) { - name = g_strdup_printf ("audio_%u", naudiopad++); - template = &audio_src_template; - } else if (track->type == GES_TRACK_TYPE_VIDEO) { - name = g_strdup_printf ("video_%u", nvideopad++); - template = &video_src_template; - } else { - GST_INFO_OBJECT (self, "Track type not handled: %" GST_PTR_FORMAT, track); - continue; - } - - queue = gst_element_factory_make ("queue", NULL); - /* Add queues the same way as in GESPipeline */ - g_object_set (G_OBJECT (queue), "max-size-buffers", 0, - "max-size-bytes", 0, "max-size-time", (gint64) 2 * GST_SECOND, NULL); - gst_bin_add (GST_BIN (self), queue); - - tmppad = gst_element_get_static_pad (queue, "sink"); - if (gst_pad_link (pad, tmppad) != GST_PAD_LINK_OK) { - GST_ERROR ("Could not link %s:%s and %s:%s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (tmppad)); - - gst_object_unref (tmppad); - gst_object_unref (queue); - continue; - } - - tmppad = gst_element_get_static_pad (queue, "src"); - gpad = gst_ghost_pad_new_from_template (name, tmppad, - gst_static_pad_template_get (template)); - - gst_pad_set_active (gpad, TRUE); - gst_element_add_pad (GST_ELEMENT (self), gpad); - } - - gst_element_sync_state_with_parent (GST_ELEMENT (self->timeline)); - - return TRUE; -} - /*** GSTURIHANDLER INTERFACE *************************************************/ static GstURIType @@ -174,9 +80,10 @@ static gchar * ges_src_uri_get_uri (GstURIHandler * handler) { GESSrc *self = GES_SRC (handler); + GESTimeline *timeline = ges_base_bin_get_timeline (GES_BASE_BIN (self)); - return self->timeline ? g_strdup_printf ("ges://%s", - GST_OBJECT_NAME (self->timeline)) : NULL; + return timeline ? g_strdup_printf ("ges://%s", + GST_OBJECT_NAME (timeline)) : NULL; } static gboolean @@ -197,65 +104,19 @@ ges_src_uri_handler_init (gpointer g_iface, gpointer iface_data) iface->set_uri = ges_src_uri_set_uri; } -G_DEFINE_TYPE_WITH_CODE (GESSrc, ges_src, GST_TYPE_BIN, +G_DEFINE_TYPE_WITH_CODE (GESSrc, ges_src, ges_base_bin_get_type (), G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, ges_src_uri_handler_init)); -static void -ges_src_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - GESSrc *self = GES_SRC (object); - - switch (property_id) { - case PROP_TIMELINE: - g_value_set_object (value, self->timeline); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -ges_src_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - GESSrc *self = GES_SRC (object); - - switch (property_id) { - case PROP_TIMELINE: - ges_src_set_timeline (self, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - static void ges_src_class_init (GESSrcClass * self_class) { - GObjectClass *gclass = G_OBJECT_CLASS (self_class); GstElementClass *gstelement_klass = GST_ELEMENT_CLASS (self_class); GST_DEBUG_CATEGORY_INIT (gessrc, "gessrc", 0, "ges src element"); - - gclass->get_property = ges_src_get_property; - gclass->set_property = ges_src_set_property; - - /** - * GESSrc:timeline: - * - * Timeline to use in this src. - */ - properties[PROP_TIMELINE] = g_param_spec_object ("timeline", "Timeline", - "Timeline to use in this src.", - GES_TYPE_TIMELINE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (gclass, PROP_LAST, properties); - - gst_element_class_add_pad_template (gstelement_klass, - gst_static_pad_template_get (&video_src_template)); - gst_element_class_add_pad_template (gstelement_klass, - gst_static_pad_template_get (&audio_src_template)); + gst_element_class_set_static_metadata (gstelement_klass, + "GStreamer Editing Services based 'source'", + "Codec/Source/Editing", + "Source for GESTimeline.", "Thibault Saunier