mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
formatters: Save and load bindings applied to sources.
This commit is contained in:
parent
6a187e09dd
commit
f1a3d65ef6
3 changed files with 119 additions and 14 deletions
|
@ -40,6 +40,14 @@ typedef struct PendingEffects
|
||||||
|
|
||||||
} PendingEffects;
|
} PendingEffects;
|
||||||
|
|
||||||
|
typedef struct PendingBinding
|
||||||
|
{
|
||||||
|
gchar *track_id;
|
||||||
|
GstControlSource *source;
|
||||||
|
gchar *propname;
|
||||||
|
gchar *binding_type;
|
||||||
|
} PendingBinding;
|
||||||
|
|
||||||
typedef struct PendingClip
|
typedef struct PendingClip
|
||||||
{
|
{
|
||||||
gchar *id;
|
gchar *id;
|
||||||
|
@ -56,6 +64,8 @@ typedef struct PendingClip
|
||||||
|
|
||||||
GList *effects;
|
GList *effects;
|
||||||
|
|
||||||
|
GList *pending_bindings;
|
||||||
|
|
||||||
/* TODO Implement asset effect management
|
/* TODO Implement asset effect management
|
||||||
* PendingTrackElements *track_elements; */
|
* PendingTrackElements *track_elements; */
|
||||||
} PendingClip;
|
} PendingClip;
|
||||||
|
@ -98,6 +108,9 @@ struct _GESBaseXmlFormatterPrivate
|
||||||
|
|
||||||
/* current track element */
|
/* current track element */
|
||||||
GESTrackElement *current_track_element;
|
GESTrackElement *current_track_element;
|
||||||
|
|
||||||
|
GESClip *current_clip;
|
||||||
|
PendingClip *current_pending_clip;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -341,6 +354,8 @@ ges_base_xml_formatter_init (GESBaseXmlFormatter * self)
|
||||||
priv->layers = g_hash_table_new_full (g_direct_hash,
|
priv->layers = g_hash_table_new_full (g_direct_hash,
|
||||||
g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
|
g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
|
||||||
priv->current_track_element = NULL;
|
priv->current_track_element = NULL;
|
||||||
|
priv->current_clip = NULL;
|
||||||
|
priv->current_pending_clip = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -366,6 +381,16 @@ ges_base_xml_formatter_class_init (GESBaseXmlFormatterClass * self_class)
|
||||||
* *
|
* *
|
||||||
***********************************************/
|
***********************************************/
|
||||||
|
|
||||||
|
|
||||||
|
static GESTrackElement *
|
||||||
|
_get_element_by_track_id (GESBaseXmlFormatterPrivate * priv,
|
||||||
|
const gchar * track_id, GESClip * clip)
|
||||||
|
{
|
||||||
|
GESTrack *track = g_hash_table_lookup (priv->tracks, track_id);
|
||||||
|
|
||||||
|
return ges_clip_find_track_element (clip, track, GES_TYPE_SOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_set_auto_transition (gpointer prio, LayerEntry * entry, gpointer udata)
|
_set_auto_transition (gpointer prio, LayerEntry * entry, gpointer udata)
|
||||||
{
|
{
|
||||||
|
@ -459,6 +484,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
|
||||||
(GstStructureForeachFunc) _set_child_property, trackelement);
|
(GstStructureForeachFunc) _set_child_property, trackelement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_free_pending_binding (PendingBinding * pend)
|
||||||
|
{
|
||||||
|
g_free (pend->propname);
|
||||||
|
g_free (pend->binding_type);
|
||||||
|
g_free (pend->track_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_free_pending_effect (PendingEffects * pend)
|
_free_pending_effect (PendingEffects * pend)
|
||||||
{
|
{
|
||||||
|
@ -480,6 +513,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
|
||||||
if (pend->properties)
|
if (pend->properties)
|
||||||
gst_structure_free (pend->properties);
|
gst_structure_free (pend->properties);
|
||||||
g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect);
|
g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect);
|
||||||
|
g_list_free_full (pend->pending_bindings,
|
||||||
|
(GDestroyNotify) _free_pending_binding);
|
||||||
g_hash_table_remove (priv->clipid_pendings, pend->id);
|
g_hash_table_remove (priv->clipid_pendings, pend->id);
|
||||||
g_slice_free (PendingClip, pend);
|
g_slice_free (PendingClip, pend);
|
||||||
}
|
}
|
||||||
|
@ -496,6 +531,22 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
|
||||||
priv->pending_assets = g_list_remove (priv->pending_assets, passet);
|
priv->pending_assets = g_list_remove (priv->pending_assets, passet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_add_pending_bindings (GESBaseXmlFormatterPrivate * priv, GList * bindings,
|
||||||
|
GESClip * clip)
|
||||||
|
{
|
||||||
|
GList *tmpbinding;
|
||||||
|
|
||||||
|
for (tmpbinding = bindings; tmpbinding; tmpbinding = tmpbinding->next) {
|
||||||
|
PendingBinding *pbinding = tmpbinding->data;
|
||||||
|
GESTrackElement *element =
|
||||||
|
_get_element_by_track_id (priv, pbinding->track_id, clip);
|
||||||
|
if (element)
|
||||||
|
ges_track_element_set_control_source (element,
|
||||||
|
pbinding->source, pbinding->propname, pbinding->binding_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
||||||
{
|
{
|
||||||
|
@ -570,6 +621,8 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
||||||
if (clip == NULL)
|
if (clip == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
_add_pending_bindings (priv, pend->pending_bindings, clip);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
|
GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
|
||||||
g_list_length (pend->effects));
|
g_list_length (pend->effects));
|
||||||
for (tmpeffect = pend->effects; tmpeffect; tmpeffect = tmpeffect->next) {
|
for (tmpeffect = pend->effects; tmpeffect; tmpeffect = tmpeffect->next) {
|
||||||
|
@ -739,6 +792,9 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
||||||
g_list_append (pendings, pclip));
|
g_list_append (pendings, pclip));
|
||||||
g_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip);
|
g_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip);
|
||||||
|
|
||||||
|
priv->current_clip = NULL;
|
||||||
|
priv->current_pending_clip = pclip;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,6 +803,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
||||||
|
|
||||||
if (!nclip)
|
if (!nclip)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
priv->current_clip = nclip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -831,12 +889,35 @@ ges_base_xml_formatter_add_track (GESBaseXmlFormatter * self,
|
||||||
void
|
void
|
||||||
ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
|
ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
|
||||||
const gchar * binding_type, const gchar * source_type,
|
const gchar * binding_type, const gchar * source_type,
|
||||||
const gchar * property_name, gint mode, GSList * timed_values)
|
const gchar * property_name, gint mode, const gchar * track_id,
|
||||||
|
GSList * timed_values)
|
||||||
{
|
{
|
||||||
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
|
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
|
||||||
GESTrackElement *element;
|
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) {
|
||||||
|
PendingBinding *pbinding;
|
||||||
|
|
||||||
|
pbinding = g_slice_new0 (PendingBinding);
|
||||||
|
pbinding->source = gst_interpolation_control_source_new ();
|
||||||
|
g_object_set (pbinding->source, "mode", mode, NULL);
|
||||||
|
gst_timed_value_control_source_set_from_list (GST_TIMED_VALUE_CONTROL_SOURCE
|
||||||
|
(pbinding->source), timed_values);
|
||||||
|
pbinding->propname = g_strdup (property_name);
|
||||||
|
pbinding->binding_type = g_strdup (binding_type);
|
||||||
|
pbinding->track_id = g_strdup (track_id);
|
||||||
|
priv->current_pending_clip->pending_bindings =
|
||||||
|
g_list_append (priv->current_pending_clip->pending_bindings, pbinding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
element = priv->current_track_element;
|
||||||
|
}
|
||||||
|
|
||||||
element = priv->current_track_element;
|
|
||||||
if (element == NULL) {
|
if (element == NULL) {
|
||||||
GST_WARNING ("No current track element to which we can append a binding");
|
GST_WARNING ("No current track element to which we can append a binding");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -212,7 +212,7 @@ void ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormat
|
||||||
gboolean variableframerate,
|
gboolean variableframerate,
|
||||||
GstStructure * properties,
|
GstStructure * properties,
|
||||||
GError ** error);
|
GError ** error);
|
||||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlFormatter *self,
|
G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlFormatter *self,
|
||||||
GType effect_type,
|
GType effect_type,
|
||||||
const gchar *asset_id,
|
const gchar *asset_id,
|
||||||
const gchar * track_id,
|
const gchar * track_id,
|
||||||
|
@ -222,12 +222,13 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlForm
|
||||||
const gchar *metadatas,
|
const gchar *metadatas,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding(GESBaseXmlFormatter * self,
|
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_bindingi (GESBaseXmlFormatter * self,
|
||||||
const gchar * binding_type,
|
const gchar * binding_type,
|
||||||
const gchar * source_type,
|
const gchar * source_type,
|
||||||
const gchar * property_name,
|
const gchar * property_name,
|
||||||
gint mode,
|
gint mode,
|
||||||
GSList * timed_values);
|
const gchar *track_id,
|
||||||
|
GSList * timed_values);
|
||||||
|
|
||||||
G_GNUC_INTERNAL void set_property_foreach (GQuark field_id,
|
G_GNUC_INTERNAL void set_property_foreach (GQuark field_id,
|
||||||
const GValue * value,
|
const GValue * value,
|
||||||
|
|
|
@ -513,7 +513,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
||||||
GESXmlFormatter * self, GError ** error)
|
GESXmlFormatter * self, GError ** error)
|
||||||
{
|
{
|
||||||
const gchar *type = NULL, *source_type = NULL, *timed_values =
|
const gchar *type = NULL, *source_type = NULL, *timed_values =
|
||||||
NULL, *property_name = NULL, *mode = NULL;
|
NULL, *property_name = NULL, *mode = NULL, *track_id = NULL;
|
||||||
gchar **pairs, **tmp;
|
gchar **pairs, **tmp;
|
||||||
gchar *pair;
|
gchar *pair;
|
||||||
GSList *list = NULL;
|
GSList *list = NULL;
|
||||||
|
@ -524,6 +524,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
||||||
G_MARKUP_COLLECT_STRING, "source_type", &source_type,
|
G_MARKUP_COLLECT_STRING, "source_type", &source_type,
|
||||||
G_MARKUP_COLLECT_STRING, "property", &property_name,
|
G_MARKUP_COLLECT_STRING, "property", &property_name,
|
||||||
G_MARKUP_COLLECT_STRING, "mode", &mode,
|
G_MARKUP_COLLECT_STRING, "mode", &mode,
|
||||||
|
G_MARKUP_COLLECT_STRING, "track_id", &track_id,
|
||||||
G_MARKUP_COLLECT_STRING, "values", &timed_values,
|
G_MARKUP_COLLECT_STRING, "values", &timed_values,
|
||||||
G_MARKUP_COLLECT_INVALID)) {
|
G_MARKUP_COLLECT_INVALID)) {
|
||||||
return;
|
return;
|
||||||
|
@ -549,10 +550,11 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
g_strfreev (pairs);
|
g_strfreev (pairs);
|
||||||
|
|
||||||
ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self),
|
ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self),
|
||||||
type,
|
type,
|
||||||
source_type,
|
source_type,
|
||||||
property_name, (gint) g_ascii_strtoll (mode, NULL, 10), list);
|
property_name, (gint) g_ascii_strtoll (mode, NULL, 10), track_id, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -809,7 +811,7 @@ _save_tracks (GString * str, GESTimeline * timeline)
|
||||||
|
|
||||||
/* TODO : Use this function for every track element with controllable properties */
|
/* TODO : Use this function for every track element with controllable properties */
|
||||||
static inline void
|
static inline void
|
||||||
_save_keyframes (GString * str, GESTrackElement * trackelement)
|
_save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
|
||||||
{
|
{
|
||||||
GHashTable *bindings_hashtable;
|
GHashTable *bindings_hashtable;
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
|
@ -839,6 +841,7 @@ _save_keyframes (GString * str, GESTrackElement * trackelement)
|
||||||
(gchar *) key));
|
(gchar *) key));
|
||||||
g_object_get (source, "mode", &mode, NULL);
|
g_object_get (source, "mode", &mode, NULL);
|
||||||
append_escaped (str, g_markup_printf_escaped (" mode='%d'", mode));
|
append_escaped (str, g_markup_printf_escaped (" mode='%d'", mode));
|
||||||
|
append_escaped (str, g_markup_printf_escaped (" track_id='%d'", index));
|
||||||
append_escaped (str, g_markup_printf_escaped (" values ='"));
|
append_escaped (str, g_markup_printf_escaped (" values ='"));
|
||||||
timed_values =
|
timed_values =
|
||||||
gst_timed_value_control_source_get_all
|
gst_timed_value_control_source_get_all
|
||||||
|
@ -917,7 +920,7 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
|
||||||
g_markup_printf_escaped (" children-properties='%s'>\n",
|
g_markup_printf_escaped (" children-properties='%s'>\n",
|
||||||
gst_structure_to_string (structure)));
|
gst_structure_to_string (structure)));
|
||||||
|
|
||||||
_save_keyframes (str, trackelement);
|
_save_keyframes (str, trackelement, -1);
|
||||||
|
|
||||||
append_escaped (str, g_markup_printf_escaped ("</effect>\n"));
|
append_escaped (str, g_markup_printf_escaped ("</effect>\n"));
|
||||||
gst_structure_free (structure);
|
gst_structure_free (structure);
|
||||||
|
@ -950,6 +953,8 @@ _save_layers (GString * str, GESTimeline * timeline)
|
||||||
clips = ges_layer_get_clips (layer);
|
clips = ges_layer_get_clips (layer);
|
||||||
for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) {
|
for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) {
|
||||||
GList *effects, *tmpeffect;
|
GList *effects, *tmpeffect;
|
||||||
|
GList *tmptrackelement;
|
||||||
|
GList *tracks;
|
||||||
|
|
||||||
clip = GES_CLIP (tmpclip->data);
|
clip = GES_CLIP (tmpclip->data);
|
||||||
effects = ges_clip_get_top_effects (clip);
|
effects = ges_clip_get_top_effects (clip);
|
||||||
|
@ -973,6 +978,24 @@ _save_layers (GString * str, GESTimeline * timeline)
|
||||||
for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next)
|
for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next)
|
||||||
_save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data),
|
_save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data),
|
||||||
timeline);
|
timeline);
|
||||||
|
|
||||||
|
tracks = ges_timeline_get_tracks (timeline);
|
||||||
|
|
||||||
|
for (tmptrackelement = GES_CONTAINER_CHILDREN (clip); tmptrackelement;
|
||||||
|
tmptrackelement = tmptrackelement->next) {
|
||||||
|
gint index;
|
||||||
|
|
||||||
|
if (!GES_IS_SOURCE (tmptrackelement->data))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
index =
|
||||||
|
g_list_index (tracks,
|
||||||
|
ges_track_element_get_track (tmptrackelement->data));
|
||||||
|
_save_keyframes (str, tmptrackelement->data, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free_full (tracks, gst_object_unref);
|
||||||
|
|
||||||
g_string_append (str, "</clip>\n");
|
g_string_append (str, "</clip>\n");
|
||||||
nbclips++;
|
nbclips++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue