mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-08 16:35:40 +00:00
formatter: save and load source's children properties
This commit is contained in:
parent
b89ffaea82
commit
84610050ae
3 changed files with 154 additions and 23 deletions
|
@ -51,6 +51,12 @@ typedef struct PendingBinding
|
|||
gchar *binding_type;
|
||||
} PendingBinding;
|
||||
|
||||
typedef struct PendingChildProperties
|
||||
{
|
||||
gchar *track_id;
|
||||
GstStructure *structure;
|
||||
} PendingChildProperties;
|
||||
|
||||
typedef struct PendingClip
|
||||
{
|
||||
gchar *id;
|
||||
|
@ -69,6 +75,8 @@ typedef struct PendingClip
|
|||
|
||||
GList *pending_bindings;
|
||||
|
||||
GList *children_props;
|
||||
|
||||
/* TODO Implement asset effect management
|
||||
* PendingTrackElements *track_elements; */
|
||||
} PendingClip;
|
||||
|
@ -513,6 +521,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
|
|||
(GstStructureForeachFunc) _set_child_property, trackelement);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_pending_children_props (PendingChildProperties * pend)
|
||||
{
|
||||
g_free (pend->track_id);
|
||||
if (pend->structure)
|
||||
gst_structure_free (pend->structure);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_pending_binding (PendingBinding * pend)
|
||||
{
|
||||
|
@ -543,6 +559,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
|
|||
g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect);
|
||||
g_list_free_full (pend->pending_bindings,
|
||||
(GDestroyNotify) _free_pending_binding);
|
||||
g_list_free_full (pend->children_props,
|
||||
(GDestroyNotify) _free_pending_children_props);
|
||||
g_hash_table_remove (priv->clipid_pendings, pend->id);
|
||||
g_free (pend->id);
|
||||
g_slice_free (PendingClip, pend);
|
||||
|
@ -560,6 +578,23 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
|
|||
g_slice_free (PendingAsset, passet);
|
||||
}
|
||||
|
||||
static void
|
||||
_add_children_properties (GESBaseXmlFormatterPrivate * priv, GList * childprops,
|
||||
GESClip * clip)
|
||||
{
|
||||
GList *tmpchildprops;
|
||||
|
||||
for (tmpchildprops = childprops; tmpchildprops;
|
||||
tmpchildprops = tmpchildprops->next) {
|
||||
PendingChildProperties *pchildprops = tmpchildprops->data;
|
||||
GESTrackElement *element =
|
||||
_get_element_by_track_id (priv, pchildprops->track_id, clip);
|
||||
if (element && pchildprops->structure)
|
||||
gst_structure_foreach (pchildprops->structure,
|
||||
(GstStructureForeachFunc) _set_child_property, element);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_add_pending_bindings (GESBaseXmlFormatterPrivate * priv, GList * bindings,
|
||||
GESClip * clip)
|
||||
|
@ -650,6 +685,7 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
|||
if (clip == NULL)
|
||||
continue;
|
||||
|
||||
_add_children_properties (priv, pend->children_props, clip);
|
||||
_add_pending_bindings (priv, pend->pending_bindings, clip);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
|
||||
|
@ -1009,6 +1045,41 @@ ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
|
|||
GST_WARNING ("This interpolation type is not supported\n");
|
||||
}
|
||||
|
||||
void
|
||||
ges_base_xml_formatter_add_source (GESBaseXmlFormatter * self,
|
||||
const gchar * track_id, GstStructure * children_properties)
|
||||
{
|
||||
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
|
||||
GESTrackElement *element = NULL;
|
||||
|
||||
if (track_id[0] != '-' && priv->current_clip)
|
||||
element = _get_element_by_track_id (priv, track_id, priv->current_clip);
|
||||
|
||||
else if (track_id[0] != '-' && priv->current_pending_clip) {
|
||||
PendingChildProperties *pchildprops;
|
||||
|
||||
pchildprops = g_slice_new0 (PendingChildProperties);
|
||||
pchildprops->track_id = g_strdup (track_id);
|
||||
pchildprops->structure = children_properties ?
|
||||
gst_structure_copy (children_properties) : NULL;
|
||||
priv->current_pending_clip->children_props =
|
||||
g_list_append (priv->current_pending_clip->children_props, pchildprops);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
element = priv->current_track_element;
|
||||
|
||||
if (element == NULL) {
|
||||
GST_WARNING
|
||||
("No current track element to which we can append children properties");
|
||||
return;
|
||||
}
|
||||
|
||||
gst_structure_foreach (children_properties,
|
||||
(GstStructureForeachFunc) _set_child_property, element);
|
||||
}
|
||||
|
||||
void
|
||||
ges_base_xml_formatter_add_track_element (GESBaseXmlFormatter * self,
|
||||
GType track_element_type, const gchar * asset_id, const gchar * track_id,
|
||||
|
|
|
@ -248,6 +248,10 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlForma
|
|||
const gchar *metadatas,
|
||||
GError **error);
|
||||
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_source (GESBaseXmlFormatter *self,
|
||||
const gchar * track_id,
|
||||
GstStructure *children_properties);
|
||||
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
|
||||
const gchar * binding_type,
|
||||
const gchar * source_type,
|
||||
|
|
|
@ -559,6 +559,43 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
|||
property_name, (gint) g_ascii_strtoll (mode, NULL, 10), track_id, list);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_parse_source (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
GESXmlFormatter * self, GError ** error)
|
||||
{
|
||||
GstStructure *children_props = NULL;
|
||||
const gchar *track_id = NULL, *children_properties = NULL;
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
G_MARKUP_COLLECT_STRING, "track-id", &track_id,
|
||||
COLLECT_STR_OPT, "children-properties", &children_properties,
|
||||
G_MARKUP_COLLECT_INVALID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (children_properties) {
|
||||
children_props = gst_structure_from_string (children_properties, NULL);
|
||||
if (children_props == NULL)
|
||||
goto wrong_children_properties;
|
||||
}
|
||||
|
||||
ges_base_xml_formatter_add_source (GES_BASE_XML_FORMATTER (self), track_id,
|
||||
children_props);
|
||||
|
||||
if (children_props)
|
||||
gst_structure_free (children_props);
|
||||
|
||||
return;
|
||||
|
||||
wrong_children_properties:
|
||||
g_set_error (error, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"element '%s', children properties '%s', could no be deserialized",
|
||||
element_name, children_properties);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_parse_effect (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
|
@ -668,6 +705,9 @@ _parse_element_start (GMarkupParseContext * context, const gchar * element_name,
|
|||
else if (g_strcmp0 (element_name, "clip") == 0)
|
||||
_parse_clip (context, element_name, attribute_names,
|
||||
attribute_values, self, error);
|
||||
else if (g_strcmp0 (element_name, "source") == 0)
|
||||
_parse_source (context, element_name, attribute_names,
|
||||
attribute_values, self, error);
|
||||
else if (g_strcmp0 (element_name, "effect") == 0)
|
||||
_parse_effect (context, element_name, attribute_names,
|
||||
attribute_values, self, error);
|
||||
|
@ -823,6 +863,37 @@ _save_tracks (GString * str, GESTimeline * timeline)
|
|||
g_list_free_full (tracks, gst_object_unref);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_save_children_properties (GString * str, GESTrackElement * trackelement)
|
||||
{
|
||||
GstStructure *structure;
|
||||
GParamSpec **pspecs, *spec;
|
||||
guint i, n_props;
|
||||
|
||||
pspecs = ges_track_element_list_children_properties (trackelement, &n_props);
|
||||
|
||||
structure = gst_structure_new_empty ("properties");
|
||||
for (i = 0; i < n_props; i++) {
|
||||
GValue val = { 0 };
|
||||
spec = pspecs[i];
|
||||
|
||||
if (_can_serialize_spec (spec)) {
|
||||
_init_value_from_spec_for_serialization (&val, spec);
|
||||
ges_track_element_get_child_property_by_pspec (trackelement, spec, &val);
|
||||
gst_structure_set_value (structure, spec->name, &val);
|
||||
g_value_unset (&val);
|
||||
}
|
||||
g_param_spec_unref (spec);
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
append_escaped (str,
|
||||
g_markup_printf_escaped (" children-properties='%s'",
|
||||
gst_structure_to_string (structure)));
|
||||
|
||||
gst_structure_free (structure);
|
||||
}
|
||||
|
||||
/* TODO : Use this function for every track element with controllable properties */
|
||||
static inline void
|
||||
_save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
|
||||
|
@ -883,10 +954,8 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
|
|||
{
|
||||
GESTrack *tck;
|
||||
GList *tmp, *tracks;
|
||||
GstStructure *structure;
|
||||
gchar *properties, *metas;
|
||||
GParamSpec **pspecs, *spec;
|
||||
guint j, n_props = 0, track_id = 0;
|
||||
guint track_id = 0;
|
||||
|
||||
tck = ges_track_element_get_track (trackelement);
|
||||
if (tck == NULL) {
|
||||
|
@ -916,30 +985,12 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
|
|||
g_free (properties);
|
||||
g_free (metas);
|
||||
|
||||
pspecs = ges_track_element_list_children_properties (trackelement, &n_props);
|
||||
structure = gst_structure_new_empty ("properties");
|
||||
for (j = 0; j < n_props; j++) {
|
||||
GValue val = { 0 };
|
||||
|
||||
spec = pspecs[j];
|
||||
if (_can_serialize_spec (spec)) {
|
||||
_init_value_from_spec_for_serialization (&val, spec);
|
||||
ges_track_element_get_child_property_by_pspec (trackelement, spec, &val);
|
||||
gst_structure_set_value (structure, spec->name, &val);
|
||||
g_value_unset (&val);
|
||||
}
|
||||
g_param_spec_unref (spec);
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
append_escaped (str,
|
||||
g_markup_printf_escaped (" children-properties='%s'>\n",
|
||||
gst_structure_to_string (structure)));
|
||||
_save_children_properties (str, trackelement);
|
||||
append_escaped (str, g_markup_printf_escaped (">\n"));
|
||||
|
||||
_save_keyframes (str, trackelement, -1);
|
||||
|
||||
append_escaped (str, g_markup_printf_escaped (" </effect>\n"));
|
||||
gst_structure_free (structure);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -1007,7 +1058,12 @@ _save_layers (GString * str, GESTimeline * timeline)
|
|||
index =
|
||||
g_list_index (tracks,
|
||||
ges_track_element_get_track (tmptrackelement->data));
|
||||
append_escaped (str,
|
||||
g_markup_printf_escaped (" <source track-id='%i'", index));
|
||||
_save_children_properties (str, tmptrackelement->data);
|
||||
append_escaped (str, g_markup_printf_escaped (">\n"));
|
||||
_save_keyframes (str, tmptrackelement->data, index);
|
||||
append_escaped (str, g_markup_printf_escaped (" </source>\n"));
|
||||
}
|
||||
|
||||
g_list_free_full (tracks, gst_object_unref);
|
||||
|
|
Loading…
Reference in a new issue