xml-formatter: Save encoder and muxer advanced settings
authorStefan Popa <stefanpopa2209@gmail.com>
Tue, 22 Aug 2017 14:23:45 +0000 (14:23 +0000)
committerThibault Saunier <thibault.saunier@osg.samsung.com>
Sat, 26 Aug 2017 14:20:42 +0000 (11:20 -0300)
Added support for saving/loading encoder and muxer advanced settings.

Differential Revision: https://phabricator.freedesktop.org/D1837

ges/ges-base-xml-formatter.c
ges/ges-internal.h
ges/ges-xml-formatter.c

index 63284ec..ede45c8 100644 (file)
@@ -792,12 +792,49 @@ done:
     _loading_done (self);
 }
 
+GstElement *
+get_element_for_encoding_profile (GstEncodingProfile * prof,
+    GstElementFactoryListType type)
+{
+  GstEncodingProfile *prof_copy;
+  GstElement *encodebin;
+  GList *tmp;
+  GstElement *element = NULL;
+
+  prof_copy = gst_encoding_profile_copy (prof);
+
+  gst_encoding_profile_set_presence (prof_copy, 1);
+  gst_encoding_profile_set_preset (prof_copy, NULL);
+
+  encodebin = gst_element_factory_make ("encodebin", NULL);
+  g_object_set (encodebin, "profile", prof_copy, NULL);
+
+  GST_OBJECT_LOCK (encodebin);
+  for (tmp = GST_BIN (encodebin)->children; tmp; tmp = tmp->next) {
+    GstElementFactory *factory;
+    factory = gst_element_get_factory (GST_ELEMENT (tmp->data));
+
+    if (factory && gst_element_factory_list_is_type (factory, type)) {
+      element = GST_ELEMENT (tmp->data);
+      gst_object_ref (element);
+      break;
+    }
+  }
+  GST_OBJECT_UNLOCK (encodebin);
+  gst_object_unref (encodebin);
+
+  gst_encoding_profile_unref (prof_copy);
+
+  return element;
+}
+
 static GstEncodingProfile *
 _create_profile (GESBaseXmlFormatter * self,
     const gchar * type, const gchar * parent, const gchar * name,
     const gchar * description, GstCaps * format, const gchar * preset,
-    const gchar * preset_name, gint id, guint presence, GstCaps * restriction,
-    guint pass, gboolean variableframerate, gboolean enabled)
+    GstStructure * preset_properties, const gchar * preset_name, gint id,
+    guint presence, GstCaps * restriction, guint pass,
+    gboolean variableframerate, gboolean enabled)
 {
   GstEncodingProfile *profile = NULL;
 
@@ -805,8 +842,6 @@ _create_profile (GESBaseXmlFormatter * self,
     profile = GST_ENCODING_PROFILE (gst_encoding_container_profile_new (name,
             description, format, preset));
     gst_encoding_profile_set_preset_name (profile, preset_name);
-
-    return profile;
   } else if (!g_strcmp0 (type, "video")) {
     GstEncodingVideoProfile *sprof = gst_encoding_video_profile_new (format,
         preset, restriction, presence);
@@ -824,10 +859,43 @@ _create_profile (GESBaseXmlFormatter * self,
     return NULL;
   }
 
-  gst_encoding_profile_set_name (profile, name);
-  gst_encoding_profile_set_enabled (profile, enabled);
-  gst_encoding_profile_set_description (profile, description);
-  gst_encoding_profile_set_preset_name (profile, preset_name);
+  if (!g_strcmp0 (type, "video") || !g_strcmp0 (type, "audio")) {
+    gst_encoding_profile_set_name (profile, name);
+    gst_encoding_profile_set_enabled (profile, enabled);
+    gst_encoding_profile_set_description (profile, description);
+    gst_encoding_profile_set_preset_name (profile, preset_name);
+  }
+
+  if (preset && preset_properties) {
+    GstElement *element;
+
+    if (!g_strcmp0 (type, "container")) {
+      element = get_element_for_encoding_profile (profile,
+          GST_ELEMENT_FACTORY_TYPE_MUXER);
+    } else {
+      element = get_element_for_encoding_profile (profile,
+          GST_ELEMENT_FACTORY_TYPE_ENCODER);
+    }
+
+    if (G_UNLIKELY (!element || !GST_IS_PRESET (element))) {
+      GST_WARNING_OBJECT (element, "Element is not a GstPreset");
+      goto done;
+    }
+
+    /* If the preset doesn't exist on the system, create it */
+    if (!gst_preset_load_preset (GST_PRESET (element), preset)) {
+      gst_structure_foreach (preset_properties,
+          (GstStructureForeachFunc) set_property_foreach, element);
+
+      if (!gst_preset_save_preset (GST_PRESET (element), preset)) {
+        GST_WARNING_OBJECT (element, "Could not save preset %s", preset);
+      }
+    }
+
+  done:
+    if (element)
+      gst_object_unref (element);
+  }
 
   return profile;
 }
@@ -1236,9 +1304,10 @@ void
 ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormatter * self,
     const gchar * type, const gchar * parent, const gchar * name,
     const gchar * description, GstCaps * format, const gchar * preset,
-    const gchar * preset_name, guint id, guint presence, GstCaps * restriction,
-    guint pass, gboolean variableframerate, GstStructure * properties,
-    gboolean enabled, GError ** error)
+    GstStructure * preset_properties, const gchar * preset_name, guint id,
+    guint presence, GstCaps * restriction, guint pass,
+    gboolean variableframerate, GstStructure * properties, gboolean enabled,
+    GError ** error)
 {
   const GList *tmp;
   GstEncodingProfile *profile;
@@ -1251,8 +1320,8 @@ ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormatter * self,
   if (parent == NULL) {
     profile =
         _create_profile (self, type, parent, name, description, format, preset,
-        preset_name, id, presence, restriction, pass, variableframerate,
-        enabled);
+        preset_properties, preset_name, id, presence, restriction, pass,
+        variableframerate, enabled);
     ges_project_add_encoding_profile (GES_FORMATTER (self)->project, profile);
     gst_object_unref (profile);
 
@@ -1285,7 +1354,8 @@ ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormatter * self,
 
   profile =
       _create_profile (self, type, parent, name, description, format, preset,
-      preset_name, id, presence, restriction, pass, variableframerate, enabled);
+      preset_properties, preset_name, id, presence, restriction, pass,
+      variableframerate, enabled);
 
   if (profile == NULL)
     goto done;
index f3b8670..3e62730 100644 (file)
@@ -20,8 +20,8 @@
 
 #ifndef __GES_INTERNAL_H__
 #define __GES_INTERNAL_H__
-
 #include <gst/gst.h>
+#include <gst/pbutils/encoding-profile.h>
 #include <gio/gio.h>
 
 #include "ges-timeline.h"
@@ -258,6 +258,7 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_encoding_profile(GESBaseXmlForma
                                                                  const gchar * description,
                                                                  GstCaps * format,
                                                                  const gchar * preset,
+                                                                 GstStructure * preset_properties,
                                                                  const gchar * preset_name,
                                                                  guint id,
                                                                  guint presence,
@@ -299,7 +300,10 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding (GESBaseXmlForma
 
 G_GNUC_INTERNAL gboolean set_property_foreach                   (GQuark field_id,
                                                                  const GValue * value,
-                                                                 GObject * object);;
+                                                                 GObject * object);
+
+G_GNUC_INTERNAL GstElement * get_element_for_encoding_profile   (GstEncodingProfile *prof,
+                                                                 GstElementFactoryListType type);
 
 /* Function to initialise GES */
 G_GNUC_INTERNAL void _init_standard_transition_assets        (void);
index 28ddf48..bf2f9c7 100644 (file)
@@ -141,8 +141,9 @@ _parse_encoding_profile (GMarkupParseContext * context,
     const gchar ** attribute_values, GESXmlFormatter * self, GError ** error)
 {
   GstCaps *capsformat = NULL;
-  const gchar *name, *description, *type, *preset = NULL, *preset_name =
-      NULL, *format;
+  GstStructure *preset_properties = NULL;
+  const gchar *name, *description, *type, *preset = NULL,
+      *str_preset_properties = NULL, *preset_name = NULL, *format;
 
   if (!g_markup_collect_attributes (element_name, attribute_names,
           attribute_values, error,
@@ -150,6 +151,7 @@ _parse_encoding_profile (GMarkupParseContext * context,
           G_MARKUP_COLLECT_STRING, "description", &description,
           G_MARKUP_COLLECT_STRING, "type", &type,
           COLLECT_STR_OPT, "preset", &preset,
+          COLLECT_STR_OPT, "preset-properties", &str_preset_properties,
           COLLECT_STR_OPT, "preset-name", &preset_name,
           COLLECT_STR_OPT, "format", &format, G_MARKUP_COLLECT_INVALID))
     return;
@@ -157,9 +159,18 @@ _parse_encoding_profile (GMarkupParseContext * context,
   if (format)
     capsformat = gst_caps_from_string (format);
 
+  if (str_preset_properties) {
+    preset_properties = gst_structure_from_string (str_preset_properties, NULL);
+    if (preset_properties == NULL) {
+      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+          "element '%s', Wrong preset-properties format.", element_name);
+      return;
+    }
+  }
+
   ges_base_xml_formatter_add_encoding_profile (GES_BASE_XML_FORMATTER (self),
-      type, NULL, name, description, capsformat, preset, preset_name, 0, 0,
-      NULL, 0, FALSE, NULL, TRUE, error);
+      type, NULL, name, description, capsformat, preset, preset_properties,
+      preset_name, 0, 0, NULL, 0, FALSE, NULL, TRUE, error);
 }
 
 static inline void
@@ -170,10 +181,11 @@ _parse_stream_profile (GMarkupParseContext * context,
   gboolean variableframerate = FALSE, enabled = TRUE;
   guint id = 0, presence = 0, pass = 0;
   GstCaps *format_caps = NULL, *restriction_caps = NULL;
+  GstStructure *preset_properties = NULL;
   const gchar *parent, *strid, *type, *strpresence, *format = NULL,
-      *name = NULL, *description = NULL, *preset, *preset_name =
-      NULL, *restriction = NULL, *strpass = NULL, *strvariableframerate = NULL,
-      *strenabled = NULL;
+      *name = NULL, *description = NULL, *preset,
+      *str_preset_properties = NULL, *preset_name = NULL, *restriction = NULL,
+      *strpass = NULL, *strvariableframerate = NULL, *strenabled = NULL;
 
   /* FIXME Looks like there is a bug in that function, if we put the parent
    * at the beginning it set %NULL and not the real value... :/ */
@@ -186,6 +198,7 @@ _parse_stream_profile (GMarkupParseContext * context,
           COLLECT_STR_OPT, "name", &name,
           COLLECT_STR_OPT, "description", &description,
           COLLECT_STR_OPT, "preset", &preset,
+          COLLECT_STR_OPT, "preset-properties", &str_preset_properties,
           COLLECT_STR_OPT, "preset-name", &preset_name,
           COLLECT_STR_OPT, "restriction", &restriction,
           COLLECT_STR_OPT, "pass", &strpass,
@@ -205,6 +218,12 @@ _parse_stream_profile (GMarkupParseContext * context,
       goto convertion_failed;
   }
 
+  if (str_preset_properties) {
+    preset_properties = gst_structure_from_string (str_preset_properties, NULL);
+    if (preset_properties == NULL)
+      goto convertion_failed;
+  }
+
   if (strpass) {
     pass = g_ascii_strtoll (strpass, NULL, 10);
     if (errno)
@@ -230,9 +249,12 @@ _parse_stream_profile (GMarkupParseContext * context,
     restriction_caps = gst_caps_from_string (restriction);
 
   ges_base_xml_formatter_add_encoding_profile (GES_BASE_XML_FORMATTER (self),
-      type, parent, name, description, format_caps, preset, preset_name, id,
-      presence, restriction_caps, pass, variableframerate, NULL, enabled,
-      error);
+      type, parent, name, description, format_caps, preset, preset_properties,
+      preset_name, id, presence, restriction_caps, pass, variableframerate,
+      NULL, enabled, error);
+
+  if (preset_properties)
+    gst_structure_free (preset_properties);
 
   return;
 
@@ -1363,9 +1385,26 @@ _save_stream_profiles (GESXmlFormatter * self, GString * str,
             description));
 
   preset = gst_encoding_profile_get_preset (sprof);
-  if (preset)
+  if (preset) {
+    GstElement *encoder;
+
     append_escaped (str, g_markup_printf_escaped ("preset='%s' ", preset));
 
+    encoder = get_element_for_encoding_profile (sprof,
+        GST_ELEMENT_FACTORY_TYPE_ENCODER);
+    if (encoder) {
+      if (GST_IS_PRESET (encoder) &&
+          gst_preset_load_preset (GST_PRESET (encoder), preset)) {
+
+        gchar *settings = _serialize_properties (G_OBJECT (encoder), NULL);
+        append_escaped (str,
+            g_markup_printf_escaped ("preset-properties='%s' ", settings));
+        g_free (settings);
+      }
+      gst_object_unref (encoder);
+    }
+  }
+
   preset_name = gst_encoding_profile_get_preset_name (sprof);
   if (preset_name)
     append_escaped (str, g_markup_printf_escaped ("preset-name='%s' ",
@@ -1416,10 +1455,33 @@ _save_encoding_profiles (GESXmlFormatter * self, GString * str,
         ("      <encoding-profile name='%s' description='%s' type='%s' ",
             profname, profdesc, proftype));
 
-    if (profpreset)
+    if (profpreset) {
+      GstElement *element;
+
       append_escaped (str, g_markup_printf_escaped ("preset='%s' ",
               profpreset));
 
+      if (GST_IS_ENCODING_CONTAINER_PROFILE (prof)) {
+        element = get_element_for_encoding_profile (prof,
+            GST_ELEMENT_FACTORY_TYPE_MUXER);
+      } else {
+        element = get_element_for_encoding_profile (prof,
+            GST_ELEMENT_FACTORY_TYPE_ENCODER);
+      }
+
+      if (element) {
+        if (GST_IS_PRESET (element) &&
+            gst_preset_load_preset (GST_PRESET (element), profpreset)) {
+          gchar *settings = _serialize_properties (G_OBJECT (element), NULL);
+          append_escaped (str,
+              g_markup_printf_escaped ("preset-properties='%s' ", settings));
+          g_free (settings);
+        }
+        gst_object_unref (element);
+      }
+
+    }
+
     if (profpresetname)
       append_escaped (str, g_markup_printf_escaped ("preset-name='%s' ",
               profpresetname));