ges: Move GESVideo/AudioSource::create_source to GESSource
[platform/upstream/gst-editing-services.git] / ges / ges-video-test-source.c
index ca171f3..7d0ae58 100644 (file)
@@ -1,6 +1,8 @@
 /* GStreamer Editing Services
  * Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
  *               2010 Nokia Corporation
+ * Copyright (C) 2020 Igalia S.L
+ *     Author: 2020 Thibault Saunier <tsaunier@igalia.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -38,20 +40,32 @@ struct _GESVideoTestSourcePrivate
 {
   GESVideoTestPattern pattern;
 
-  gboolean use_overlay;
-  GstElement *overlay;
-  GstPad *is_passthrough_pad;
-  GstPad *os_passthrough_pad;
-  GstPad *is_overlay_pad;
-  GstPad *os_overlay_pad;
-
   GstElement *capsfilter;
 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GESVideoTestSource, ges_video_test_source,
-    GES_TYPE_VIDEO_SOURCE);
+static void
+ges_extractable_interface_init (GESExtractableInterface * iface)
+{
+  iface->check_id = ges_test_source_asset_check_id;
+  iface->asset_type = GES_TYPE_TRACK_ELEMENT_ASSET;
+}
+
+static GstStructure *
+ges_video_test_source_asset_get_config (GESAsset * asset)
+{
+  const gchar *id = ges_asset_get_id (asset);
+  if (g_strcmp0 (id, g_type_name (ges_asset_get_extractable_type (asset))))
+    return gst_structure_from_string (ges_asset_get_id (asset), NULL);
+
+  return NULL;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GESVideoTestSource, ges_video_test_source,
+    GES_TYPE_VIDEO_SOURCE, G_ADD_PRIVATE (GESVideoTestSource)
+    G_IMPLEMENT_INTERFACE (GES_TYPE_EXTRACTABLE,
+        ges_extractable_interface_init));
 
-static GstElement *ges_video_test_source_create_source (GESTrackElement * self);
+static GstElement *ges_video_test_source_create_source (GESSource * source);
 
 static gboolean
 get_natural_size (GESVideoSource * source, gint * width, gint * height)
@@ -74,133 +88,42 @@ get_natural_size (GESVideoSource * source, gint * width, gint * height)
   return TRUE;
 }
 
-enum
-{
-  PROP_0,
-  PROP_USE_TIME_OVERLAY,
-  PROP_LAST
-};
-
-static GParamSpec *properties[PROP_LAST];
-
-static void
-get_property (GObject * object, guint property_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (object);
-
-  switch (property_id) {
-    case PROP_USE_TIME_OVERLAY:
-      g_value_set_boolean (value, self->priv->use_overlay);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-  }
-}
-
-static void
-set_property (GObject * object, guint property_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (object);
-
-  switch (property_id) {
-    case PROP_USE_TIME_OVERLAY:
-    {
-      GstElement *os, *is;
-      gboolean used_overlay = self->priv->use_overlay;
-
-      if (!self->priv->overlay) {
-        GST_ERROR_OBJECT (object, "Overlaying is disabled, you are probably"
-            "missing some GStreamer plugin");
-        return;
-      }
-
-      self->priv->use_overlay = g_value_get_boolean (value);
-      if (used_overlay == self->priv->use_overlay)
-        return;
-
-      is = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (self->
-                  priv->is_overlay_pad)));
-
-      if (!is)
-        return;
-
-      os = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (self->
-                  priv->os_overlay_pad)));
-      if (!os) {
-        gst_object_unref (is);
-        return;
-      }
-
-      g_object_set (is, "active-pad",
-          self->priv->use_overlay ? self->priv->is_overlay_pad : self->
-          priv->is_passthrough_pad, NULL);
-      g_object_set (os, "active-pad",
-          self->priv->use_overlay ? self->priv->os_overlay_pad : self->
-          priv->os_passthrough_pad, NULL);
-
-      gst_object_unref (is);
-      gst_object_unref (os);
-
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-  }
-}
-
-static void
-_set_child_property (GESTimelineElement * self, GObject * child,
-    GParamSpec * pspec, GValue * value)
-{
-  GstElementFactory *f =
-      GST_IS_ELEMENT (child) ? gst_element_get_factory (GST_ELEMENT (child)) :
-      NULL;
-
-  if (!f || g_strcmp0 (GST_OBJECT_NAME (f), "timeoverlay"))
-    goto done;
-
-  GST_INFO_OBJECT (self, "Activating time overlay as time mode is being set");
-  g_object_set (self, "use-time-overlay", TRUE, NULL);
-
-done:
-  GES_TIMELINE_ELEMENT_CLASS (ges_video_test_source_parent_class)
-      ->set_child_property (self, child, pspec, value);
-}
-
 static gboolean
 _set_parent (GESTimelineElement * element, GESTimelineElement * parent)
 {
+  gint width, height, fps_n, fps_d;
+  GstCaps *caps;
   GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (element);
 
 
-  if (parent) {
-    gint width, height, fps_n, fps_d;
-    GstCaps *caps;
-
-    g_assert (self->priv->capsfilter);
-    /* Setting the parent ourself as we need it to get the natural size */
-    element->parent = parent;
-    if (!ges_video_source_get_natural_size (GES_VIDEO_SOURCE (self), &width,
-            &height)) {
-      width = DEFAULT_WIDTH;
-      height = DEFAULT_HEIGHT;
-    }
-    if (!ges_timeline_element_get_natural_framerate (parent, &fps_n, &fps_d)) {
-      fps_n = DEFAULT_FRAMERATE_N;
-      fps_d = DEFAULT_FRAMERATE_D;
-    }
+  if (!parent)
+    goto done;
 
-    caps = gst_caps_new_simple ("video/x-raw",
-        "width", G_TYPE_INT, width,
-        "height", G_TYPE_INT, height,
-        "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
-    g_object_set (self->priv->capsfilter, "caps", caps, NULL);
-    gst_caps_unref (caps);
+  g_assert (self->priv->capsfilter);
+  /* Setting the parent ourself as we need it to get the natural size */
+  element->parent = parent;
+  if (!ges_video_source_get_natural_size (GES_VIDEO_SOURCE (self), &width,
+          &height)) {
+    width = DEFAULT_WIDTH;
+    height = DEFAULT_HEIGHT;
   }
 
-  return TRUE;
+  if (!ges_timeline_element_get_natural_framerate (parent, &fps_n, &fps_d)) {
+    fps_n = DEFAULT_FRAMERATE_N;
+    fps_d = DEFAULT_FRAMERATE_D;
+  }
+
+  caps = gst_caps_new_simple ("video/x-raw",
+      "width", G_TYPE_INT, width,
+      "height", G_TYPE_INT, height,
+      "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
+  g_object_set (self->priv->capsfilter, "caps", caps, NULL);
+  gst_caps_unref (caps);
+
+done:
+  return
+      GES_TIMELINE_ELEMENT_CLASS
+      (ges_video_test_source_parent_class)->set_parent (element, parent);
 }
 
 static gboolean
@@ -231,13 +154,6 @@ _get_natural_framerate (GESTimelineElement * element, gint * fps_n,
 static void
 dispose (GObject * object)
 {
-  GESVideoTestSourcePrivate *priv = GES_VIDEO_TEST_SOURCE (object)->priv;
-
-  gst_clear_object (&priv->is_overlay_pad);
-  gst_clear_object (&priv->is_passthrough_pad);
-  gst_clear_object (&priv->os_overlay_pad);
-  gst_clear_object (&priv->os_passthrough_pad);
-
   G_OBJECT_CLASS (ges_video_test_source_parent_class)->dispose (object);
 }
 
@@ -245,38 +161,17 @@ static void
 ges_video_test_source_class_init (GESVideoTestSourceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
+  GESVideoSourceClass *vsource_class = GES_VIDEO_SOURCE_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   source_class->create_source = ges_video_test_source_create_source;
-  source_class->ABI.abi.get_natural_size = get_natural_size;
-
-  /**
-   * GESVideoTestSource:use-overlay:
-   *
-   * Whether to overlay the test video source with a clock time.
-   * This property is also registered as a child property for the video
-   * test source, so you can set it like any other child property.
-   *
-   * The properties of the corresponding #timeoverlay are also registered
-   * as children properties. If you set any child property from the underlying
-   * `timeoverlay`, this property will be set to %TRUE by default.
-   */
-  properties[PROP_USE_TIME_OVERLAY] =
-      g_param_spec_boolean ("use-time-overlay", "Use-time-overlay",
-      "Use time overlay, setting a child property corresponding to"
-      "GstTimeOverlay will switch this on by default.", FALSE,
-      G_PARAM_READWRITE);
-
-  object_class->get_property = get_property;
-  object_class->set_property = set_property;
+  vsource_class->ABI.abi.get_natural_size = get_natural_size;
+
   object_class->dispose = dispose;
 
-  GES_TIMELINE_ELEMENT_CLASS (klass)->set_child_property = _set_child_property;
   GES_TIMELINE_ELEMENT_CLASS (klass)->set_parent = _set_parent;
   GES_TIMELINE_ELEMENT_CLASS (klass)->get_natural_framerate =
       _get_natural_framerate;
-
-  g_object_class_install_properties (object_class, PROP_LAST, properties);
 }
 
 static void
@@ -287,75 +182,56 @@ ges_video_test_source_init (GESVideoTestSource * self)
   self->priv->pattern = DEFAULT_VPATTERN;
 }
 
-#define CREATE_ELEMENT(var, ename)                                             \
-  if (!(var = gst_element_factory_make(ename, NULL))) {                        \
-    GST_ERROR_OBJECT(self, "Could not create %s", ename);                      \
-    goto done;                                                                 \
-  }                                                                            \
-  gst_object_ref(var);
+static GstStructure *
+ges_video_test_source_get_config (GESVideoTestSource * self)
+{
+  GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (self));
+  if (asset)
+    return ges_video_test_source_asset_get_config (asset);
+
+  return NULL;
+}
 
 static GstElement *
 ges_video_test_source_create_overlay (GESVideoTestSource * self)
 {
-  GstElement *bin = NULL, *os = NULL, *is = NULL, *toverlay = NULL, *tcstamper =
-      NULL;
-  GstPad *tmppad;
-
-  CREATE_ELEMENT (os, "output-selector");
-  CREATE_ELEMENT (is, "input-selector");
-  CREATE_ELEMENT (tcstamper, "timecodestamper");
-  CREATE_ELEMENT (toverlay, "timeoverlay");
-
-  bin = gst_bin_new (NULL);
+  const gchar *bindesc = NULL;
+  GstStructure *config = ges_video_test_source_get_config (self);
 
-  gst_bin_add_many (GST_BIN (bin), os, is, tcstamper, toverlay, NULL);
-  self->priv->os_passthrough_pad = gst_element_get_request_pad (os, "src_%u");
-  self->priv->is_passthrough_pad = gst_element_get_request_pad (is, "sink_%u");
+  if (!config)
+    return NULL;
 
-  gst_pad_link_full (self->priv->os_passthrough_pad,
-      self->priv->is_passthrough_pad, GST_PAD_LINK_CHECK_NOTHING);
-  gst_element_link (tcstamper, toverlay);
+  if (gst_structure_has_name (config, "time-overlay")) {
+    gboolean disable_timecodestamper;
 
-  self->priv->os_overlay_pad = gst_element_get_request_pad (os, "src_%u");
-  tmppad = gst_element_get_static_pad (tcstamper, "sink");
-  gst_pad_link_full (self->priv->os_overlay_pad, tmppad,
-      GST_PAD_LINK_CHECK_NOTHING);
-  gst_object_unref (tmppad);
-
-  tmppad = gst_element_get_static_pad (toverlay, "src");
-  self->priv->is_overlay_pad = gst_element_get_request_pad (is, "sink_%u");
-  gst_pad_link_full (tmppad, self->priv->is_overlay_pad,
-      GST_PAD_LINK_CHECK_NOTHING);
-  gst_object_unref (tmppad);
-
-  tmppad = gst_element_get_static_pad (os, "sink");
-  gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", tmppad));
-  gst_object_unref (tmppad);
-
-  tmppad = gst_element_get_static_pad (is, "src");
-  gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", tmppad));
-  gst_object_unref (tmppad);
+    if (gst_structure_get_boolean (config, "disable-timecodestamper",
+            &disable_timecodestamper))
+      bindesc = "timeoverlay";
+    else
+      bindesc = "timecodestamper ! timeoverlay";
+  }
+  gst_structure_free (config);
 
-done:
-  gst_clear_object (&os);
-  gst_clear_object (&is);
-  gst_clear_object (&tcstamper);
-  gst_clear_object (&toverlay);
+  if (!bindesc)
+    return NULL;
 
-  return bin;
+  return gst_parse_bin_from_description (bindesc, TRUE, NULL);
 }
 
 static GstElement *
-ges_video_test_source_create_source (GESTrackElement * element)
+ges_video_test_source_create_source (GESSource * source)
 {
   GstCaps *caps;
   gint pattern;
   GstElement *testsrc, *res;
-  const gchar *props[] = { "pattern", NULL };
+  GstElement *overlay;
+  const gchar *props[] =
+      { "pattern", "background-color", "foreground-color", NULL };
   GPtrArray *elements;
-  GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (element);
+  GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (source);
+  GESTrackElement *element = GES_TRACK_ELEMENT (source);
 
-  g_assert (!GES_TIMELINE_ELEMENT_PARENT (element));
+  g_assert (!GES_TIMELINE_ELEMENT_PARENT (source));
   testsrc = gst_element_factory_make ("videotestsrc", NULL);
   self->priv->capsfilter = gst_element_factory_make ("capsfilter", NULL);
   pattern = self->priv->pattern;
@@ -372,24 +248,22 @@ ges_video_test_source_create_source (GESTrackElement * element)
   g_object_set (self->priv->capsfilter, "caps", caps, NULL);
   gst_caps_unref (caps);
 
-  self->priv->overlay = ges_video_test_source_create_overlay (self);
-  if (self->priv->overlay) {
+  overlay = ges_video_test_source_create_overlay (self);
+  if (overlay) {
     const gchar *overlay_props[] =
         { "time-mode", "text-y", "text-x", "text-width", "test-height",
       "halignment", "valignment", "font-desc", NULL
     };
 
-    ges_track_element_add_children_props (element, self->priv->overlay, NULL,
+    ges_track_element_add_children_props (element, overlay, NULL,
         NULL, overlay_props);
-    ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (self),
-        properties[PROP_USE_TIME_OVERLAY], G_OBJECT (self));
-    g_ptr_array_add (elements, self->priv->overlay);
+    g_ptr_array_add (elements, overlay);
   }
 
   ges_track_element_add_children_props (element, testsrc, NULL, NULL, props);
 
-  res = ges_source_create_topbin ("videotestsrc", testsrc, elements);
-  g_ptr_array_free (elements, TRUE);
+  res = ges_source_create_topbin (GES_SOURCE (element), "videotestsrc", testsrc,
+      elements);
 
   return res;
 }
@@ -438,7 +312,8 @@ ges_video_test_source_get_pattern (GESVideoTestSource * source)
   return g_value_get_enum (&val);
 }
 
-/* ges_video_test_source_new:
+/**
+ * ges_video_test_source_new:
  *
  * Creates a new #GESVideoTestSource.
  *