plugins:ges: Factor out a GESBaseBin class
authorThibault Saunier <tsaunier@igalia.com>
Thu, 6 Jun 2019 17:51:45 +0000 (13:51 -0400)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 5 Jul 2019 21:50:57 +0000 (17:50 -0400)
And use it in both gesdemux and gessrc

docs/gst_plugins_cache.json
plugins/ges/gesbasebin.c [new file with mode: 0644]
plugins/ges/gesbasebin.h [new file with mode: 0644]
plugins/ges/gesdemux.c
plugins/ges/gessrc.c
plugins/ges/meson.build

index 938f8b5..717f7ff 100644 (file)
@@ -8,6 +8,7 @@
                 "description": "Demuxer for complex timeline file formats using GES.",
                 "hierarchy": [
                     "GESDemux",
+                    "GESBaseBin",
                     "GstBin",
                     "GstElement",
                     "GstObject",
                         "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",
                 }
             },
             "gessrc": {
-                "author": "Erik Walthinsen <omega@cse.ogi.edu>,Wim Taymans <wim.taymans@gmail.com>",
-                "description": "Simple container object",
+                "author": "Thibault Saunier <tsaunier@igalia.com",
+                "description": "Source for GESTimeline.",
                 "hierarchy": [
                     "GESSrc",
+                    "GESBaseBin",
                     "GstBin",
                     "GstElement",
                     "GstObject",
                     "GInitiallyUnowned",
                     "GObject"
                 ],
-                "klass": "Generic/Bin",
-                "long-name": "Generic bin",
+                "klass": "Codec/Source/Editing",
+                "long-name": "GStreamer Editing Services based 'source'",
                 "pad-templates": {
                     "audio_src": {
                         "caps": "audio/x-raw(ANY):\n",
diff --git a/plugins/ges/gesbasebin.c b/plugins/ges/gesbasebin.c
new file mode 100644 (file)
index 0000000..e39e4f3
--- /dev/null
@@ -0,0 +1,258 @@
+/* GStreamer GES plugin
+ *
+ * Copyright (C) 2019 Thibault Saunier <tsaunier@igalia.com>
+ *
+ * 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 (file)
index 0000000..a48adb4
--- /dev/null
@@ -0,0 +1,44 @@
+/* GStreamer GES plugin
+ *
+ * Copyright (C) 2019 Thibault Saunier <tsaunier@igalia.com>
+ *
+ * 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 <gst/gst.h>
+#include <gst/base/gstflowcombiner.h>
+#include <ges/ges.h>
+
+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
index ca9f49e..62ff2c0 100644 (file)
 #include "config.h"
 #endif
 
+#include "gesbasebin.h"
+
 #include <gst/gst.h>
 #include <glib/gstdio.h>
 #include <gst/pbutils/pbutils.h>
 #include <gst/base/gstadapter.h>
 #include <ges/ges.h>
-#include <gst/base/gstflowcombiner.h>
 
 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);
@@ -220,23 +103,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)
 {
   GObjectClass *gclass = G_OBJECT_CLASS (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 <tsaunier@igalia.com");
-
-  gst_element_class_add_pad_template (gstelement_klass,
-      gst_static_pad_template_get (&sink_template));
-  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));
 }
 
 typedef struct
@@ -453,7 +311,7 @@ ges_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 
         GST_INFO_OBJECT (self, "Timeline properly loaded: %" GST_PTR_FORMAT,
             data.timeline);
-        ges_demux_set_timeline (self, data.timeline);
+        ges_base_bin_set_timeline (GES_BASE_BIN (self), data.timeline);
       done:
         g_free (filename);
         g_free (uri);
@@ -496,7 +354,6 @@ ges_demux_init (GESDemux * self)
   gst_element_add_pad (GST_ELEMENT (self), self->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));
index 29dc897..2eb574d 100644 (file)
 #include <gst/gst.h>
 #include <ges/ges.h>
 
+#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 <tsaunier@igalia.com");
 }
 
 static void
index 7c74fd9..14a1712 100644 (file)
@@ -1,4 +1,4 @@
-gstges_sources = ['gesplugin.c', 'gessrc.c', 'gesdemux.c']
+gstges_sources = ['gesplugin.c', 'gessrc.c', 'gesdemux.c', 'gesbasebin.c']
 
 gstges = library('gstges', gstges_sources,
   dependencies : [gst_dep, ges_dep],