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;
|
||||
|
||||
typedef struct PendingBinding
|
||||
{
|
||||
gchar *track_id;
|
||||
GstControlSource *source;
|
||||
gchar *propname;
|
||||
gchar *binding_type;
|
||||
} PendingBinding;
|
||||
|
||||
typedef struct PendingClip
|
||||
{
|
||||
gchar *id;
|
||||
|
@ -56,6 +64,8 @@ typedef struct PendingClip
|
|||
|
||||
GList *effects;
|
||||
|
||||
GList *pending_bindings;
|
||||
|
||||
/* TODO Implement asset effect management
|
||||
* PendingTrackElements *track_elements; */
|
||||
} PendingClip;
|
||||
|
@ -98,6 +108,9 @@ struct _GESBaseXmlFormatterPrivate
|
|||
|
||||
/* current track element */
|
||||
GESTrackElement *current_track_element;
|
||||
|
||||
GESClip *current_clip;
|
||||
PendingClip *current_pending_clip;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -341,6 +354,8 @@ ges_base_xml_formatter_init (GESBaseXmlFormatter * self)
|
|||
priv->layers = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
|
||||
priv->current_track_element = NULL;
|
||||
priv->current_clip = NULL;
|
||||
priv->current_pending_clip = NULL;
|
||||
}
|
||||
|
||||
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
|
||||
_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);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_pending_binding (PendingBinding * pend)
|
||||
{
|
||||
g_free (pend->propname);
|
||||
g_free (pend->binding_type);
|
||||
g_free (pend->track_id);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_pending_effect (PendingEffects * pend)
|
||||
{
|
||||
|
@ -480,6 +513,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
|
|||
if (pend->properties)
|
||||
gst_structure_free (pend->properties);
|
||||
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_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);
|
||||
}
|
||||
|
||||
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
|
||||
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)
|
||||
continue;
|
||||
|
||||
_add_pending_bindings (priv, pend->pending_bindings, clip);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
|
||||
g_list_length (pend->effects));
|
||||
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_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip);
|
||||
|
||||
priv->current_clip = NULL;
|
||||
priv->current_pending_clip = pclip;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -747,6 +803,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
|||
|
||||
if (!nclip)
|
||||
return;
|
||||
|
||||
priv->current_clip = nclip;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -831,12 +889,35 @@ ges_base_xml_formatter_add_track (GESBaseXmlFormatter * self,
|
|||
void
|
||||
ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
|
||||
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);
|
||||
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) {
|
||||
GST_WARNING ("No current track element to which we can append a binding");
|
||||
return;
|
||||
|
|
|
@ -212,7 +212,7 @@ void ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormat
|
|||
gboolean variableframerate,
|
||||
GstStructure * properties,
|
||||
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,
|
||||
const gchar *asset_id,
|
||||
const gchar * track_id,
|
||||
|
@ -222,12 +222,13 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlForm
|
|||
const gchar *metadatas,
|
||||
GError **error);
|
||||
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding(GESBaseXmlFormatter * self,
|
||||
const gchar * binding_type,
|
||||
const gchar * source_type,
|
||||
const gchar * property_name,
|
||||
gint mode,
|
||||
GSList * timed_values);
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_bindingi (GESBaseXmlFormatter * self,
|
||||
const gchar * binding_type,
|
||||
const gchar * source_type,
|
||||
const gchar * property_name,
|
||||
gint mode,
|
||||
const gchar *track_id,
|
||||
GSList * timed_values);
|
||||
|
||||
G_GNUC_INTERNAL void set_property_foreach (GQuark field_id,
|
||||
const GValue * value,
|
||||
|
|
|
@ -513,7 +513,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
|||
GESXmlFormatter * self, GError ** error)
|
||||
{
|
||||
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 *pair;
|
||||
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, "property", &property_name,
|
||||
G_MARKUP_COLLECT_STRING, "mode", &mode,
|
||||
G_MARKUP_COLLECT_STRING, "track_id", &track_id,
|
||||
G_MARKUP_COLLECT_STRING, "values", &timed_values,
|
||||
G_MARKUP_COLLECT_INVALID)) {
|
||||
return;
|
||||
|
@ -549,10 +550,11 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
|
|||
}
|
||||
|
||||
g_strfreev (pairs);
|
||||
|
||||
ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self),
|
||||
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
|
||||
|
@ -809,7 +811,7 @@ _save_tracks (GString * str, GESTimeline * timeline)
|
|||
|
||||
/* TODO : Use this function for every track element with controllable properties */
|
||||
static inline void
|
||||
_save_keyframes (GString * str, GESTrackElement * trackelement)
|
||||
_save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
|
||||
{
|
||||
GHashTable *bindings_hashtable;
|
||||
GHashTableIter iter;
|
||||
|
@ -839,6 +841,7 @@ _save_keyframes (GString * str, GESTrackElement * trackelement)
|
|||
(gchar *) key));
|
||||
g_object_get (source, "mode", &mode, NULL);
|
||||
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 ='"));
|
||||
timed_values =
|
||||
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",
|
||||
gst_structure_to_string (structure)));
|
||||
|
||||
_save_keyframes (str, trackelement);
|
||||
_save_keyframes (str, trackelement, -1);
|
||||
|
||||
append_escaped (str, g_markup_printf_escaped ("</effect>\n"));
|
||||
gst_structure_free (structure);
|
||||
|
@ -950,6 +953,8 @@ _save_layers (GString * str, GESTimeline * timeline)
|
|||
clips = ges_layer_get_clips (layer);
|
||||
for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) {
|
||||
GList *effects, *tmpeffect;
|
||||
GList *tmptrackelement;
|
||||
GList *tracks;
|
||||
|
||||
clip = GES_CLIP (tmpclip->data);
|
||||
effects = ges_clip_get_top_effects (clip);
|
||||
|
@ -973,6 +978,24 @@ _save_layers (GString * str, GESTimeline * timeline)
|
|||
for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next)
|
||||
_save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data),
|
||||
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");
|
||||
nbclips++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue