/* GESAsset vmethod implementation */ static GESExtractable * ges_project_extract (GESAsset * project, GError ** error) { GESTimeline *timeline = g_object_new (GES_TYPE_TIMELINE, NULL); ges_extractable_set_asset (GES_EXTRACTABLE (timeline), GES_ASSET (project)); if (_load_project (GES_PROJECT (project), timeline, error)) return GES_EXTRACTABLE (timeline); gst_object_unref (timeline); return NULL; }
/** * ges_timeline_element_copy: * @self: The #GESTimelineElement to copy * @deep: whether we want to create the elements @self contains or not * * Copies @self * * Returns: (transfer floating): The newly create #GESTimelineElement, copied from @self */ GESTimelineElement * ges_timeline_element_copy (GESTimelineElement * self, gboolean deep) { GESAsset *asset; GParameter *params; GParamSpec **specs; GESTimelineElementClass *klass; guint n, n_specs, n_params; GESTimelineElement *ret = NULL; g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE); klass = GES_TIMELINE_ELEMENT_GET_CLASS (self); specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_specs); params = g_new0 (GParameter, n_specs); n_params = 0; for (n = 0; n < n_specs; ++n) { /* We do not want the timeline or the name to be copied */ if (g_strcmp0 (specs[n]->name, "parent") && g_strcmp0 (specs[n]->name, "timeline") && g_strcmp0 (specs[n]->name, "name") && (specs[n]->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE) { params[n_params].name = g_intern_string (specs[n]->name); g_value_init (¶ms[n_params].value, specs[n]->value_type); g_object_get_property (G_OBJECT (self), specs[n]->name, ¶ms[n_params].value); ++n_params; } } ret = g_object_newv (G_OBJECT_TYPE (self), n_params, params); g_free (specs); g_free (params); asset = ges_extractable_get_asset (GES_EXTRACTABLE (self)); if (asset) ges_extractable_set_asset (GES_EXTRACTABLE (ret), asset); if (deep) { if (klass->deep_copy) klass->deep_copy (self, ret); else GST_WARNING_OBJECT (self, "No deep_copy virtual method implementation" " on class %s. Can not finish the copy", G_OBJECT_CLASS_NAME (klass)); } return ret; }
/** * ges_project_load: * @project: A #GESProject that has an @uri set already * @timeline: A blank timeline to load @project into * @error: (out) (allow-none): An error to be set in case something wrong happens or %NULL * * Loads @project into @timeline * * Returns: %TRUE if the project could be loaded %FALSE otherwize. */ gboolean ges_project_load (GESProject * project, GESTimeline * timeline, GError ** error) { g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE); g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (ges_project_get_uri (project), FALSE); g_return_val_if_fail ( (ges_extractable_get_asset (GES_EXTRACTABLE (timeline)) == NULL), FALSE); if (!_load_project (project, timeline, error)) return FALSE; ges_extractable_set_asset (GES_EXTRACTABLE (timeline), GES_ASSET (project)); return TRUE; }
static void new_asset_cb (GESAsset * source, GAsyncResult * res, NewAssetUData * udata) { GError *error = NULL; GESAsset *asset = ges_asset_request_finish (res, &error); GST_DEBUG_OBJECT (udata->layer, "%" GST_PTR_FORMAT " Asset loaded, " "setting its asset", udata->clip); if (error) { GESProject *project = udata->layer->timeline ? GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE (udata->layer->timeline))) : NULL; if (project) { gchar *possible_id; possible_id = ges_project_try_updating_id (project, source, error); if (possible_id) { ges_asset_request_async (ges_asset_get_extractable_type (source), possible_id, NULL, (GAsyncReadyCallback) new_asset_cb, udata); g_free (possible_id); return; } } GST_ERROR ("Asset could not be created for uri %s, error: %s", ges_asset_get_id (asset), error->message); } else { GESProject *project = udata->layer->timeline ? GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE (udata->layer->timeline))) : NULL; ges_extractable_set_asset (GES_EXTRACTABLE (udata->clip), asset); ges_project_add_asset (project, asset); ges_layer_add_clip (udata->layer, udata->clip); } gst_object_unref (asset); g_slice_free (NewAssetUData, udata); }
/* GESAsset vmethod implementation */ static GESExtractable * ges_project_extract (GESAsset * project, GError ** error) { GESTimeline *timeline = ges_timeline_new (); if (_load_project (GES_PROJECT (project), timeline, error)) return GES_EXTRACTABLE (timeline); gst_object_unref (timeline); return NULL; }
static GstElement * ges_multi_file_source_create_source (GESTrackElement * track_element) { GESMultiFileSource *self; GstElement *bin, *src, *decodebin; GstCaps *disc_caps; GstDiscovererStreamInfo *stream_info; GValue fps = G_VALUE_INIT; GstCaps *caps; GESUriSourceAsset *asset; GESMultiFileURI *uri_data; self = (GESMultiFileSource *) track_element; asset = GES_URI_SOURCE_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (self))); if (asset != NULL) { stream_info = ges_uri_source_asset_get_stream_info (asset); g_assert (stream_info); disc_caps = gst_discoverer_stream_info_get_caps (stream_info); caps = gst_caps_copy (disc_caps); GST_DEBUG ("Got some nice caps %s", gst_caps_to_string (disc_caps)); gst_object_unref (stream_info); gst_caps_unref (disc_caps); } else { caps = gst_caps_new_empty (); GST_WARNING ("Could not extract asset."); } g_value_init (&fps, GST_TYPE_FRACTION); gst_value_set_fraction (&fps, 25, 1); gst_caps_set_value (caps, "framerate", &fps); bin = GST_ELEMENT (gst_bin_new ("multi-image-bin")); src = gst_element_factory_make ("multifilesrc", NULL); uri_data = ges_multi_file_uri_new (self->uri); g_object_set (src, "start-index", uri_data->start, "stop-index", uri_data->end, "caps", caps, "location", uri_data->location, NULL); g_free (uri_data); decodebin = gst_element_factory_make ("decodebin", NULL); gst_bin_add_many (GST_BIN (bin), src, decodebin, NULL); gst_element_link_pads_full (src, "src", decodebin, "sink", GST_PAD_LINK_CHECK_NOTHING); g_signal_connect (G_OBJECT (decodebin), "pad-added", G_CALLBACK (pad_added_cb), bin); return bin; }
GESTimeline * compTL (void) { GESTimeline *timeline; GESTrack *trackv; timeline = ges_timeline_new (); trackv = GES_TRACK (ges_video_track_new ()); ges_timeline_add_track (timeline, trackv); const gchar *assets[] = { "image/vieh.png", "image/PNG_transparency_demonstration_1.png", "image/Ice_Cream.png", "image/Fish.png" }; guint asset_count = 4; for (int i = 1; i <= asset_count; i++) { GESLayer *layer = ges_layer_new (); ges_timeline_add_layer (timeline, layer); g_object_set (layer, "priority", i - 1, NULL); GESClip *vieh = ges_clip_from_rel_path (assets[i - 1], layer, 0, 0, 10, GES_TRACK_TYPE_VIDEO); GESTrackElement *elem = ges_clip_find_track_element (vieh, trackv, G_TYPE_NONE); GESUriClipAsset *asset = GES_URI_CLIP_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (vieh))); guint width = ges_asset_get_width (asset); guint height = ges_asset_get_height (asset); g_print ("%s: %dx%d\n", assets[i - 1], width, height); ges_track_element_set_child_properties (elem, "posx", i * 100, "posy", i * 100, "width", i * 100 * width / height, "height", (i * 100) - 1, NULL); } GESLayer *backgroud_layer = ges_layer_new (); ges_timeline_add_layer (timeline, backgroud_layer); g_object_set (backgroud_layer, "priority", asset_count, NULL); ges_clip_from_rel_path ("image/wallpaper-2597248.jpg", backgroud_layer, 0, 0, 10, GES_TRACK_TYPE_VIDEO); ges_timeline_commit (timeline); return timeline; }
/* Internal methods */ static void ges_transition_clip_update_vtype_internal (GESClip * self, GESVideoStandardTransitionType value, gboolean set_asset) { GSList *tmp; guint index; GEnumClass *enum_class; const gchar *asset_id = NULL; GESTransitionClip *trself = GES_TRANSITION_CLIP (self); enum_class = g_type_class_peek (GES_VIDEO_STANDARD_TRANSITION_TYPE_TYPE); for (index = 0; index < enum_class->n_values; index++) { if (enum_class->values[index].value == value) { asset_id = enum_class->values[index].value_nick; break; } } if (asset_id == NULL) { GST_WARNING_OBJECT (self, "Wrong transition type value: %i can not set it", value); return; } for (tmp = trself->priv->video_transitions; tmp; tmp = tmp->next) { if (!ges_video_transition_set_transition_type (GES_VIDEO_TRANSITION (tmp->data), value)) return; } trself->vtype = value; trself->priv->vtype_name = asset_id; if (set_asset) { /* We already checked the value, so we can be sure no error will accured */ ges_extractable_set_asset (GES_EXTRACTABLE (self), ges_asset_request (GES_TYPE_TRANSITION_CLIP, asset_id, NULL)); } }
/** * ges_project_save: * @project: A #GESProject to save * @timeline: The #GESTimeline to save, it must have been extracted from @project * @uri: The uri where to save @project and @timeline * @formatter_asset: (allow-none): The formatter asset to use or %NULL. If %NULL, * will try to save in the same format as the one from which the timeline as been loaded * or default to the formatter with highest rank * @overwrite: %TRUE to overwrite file if it exists * @error: (out) (allow-none): An error to be set in case something wrong happens or %NULL * * Save the timeline of @project to @uri. You should make sure that @timeline * is one of the timelines that have been extracted from @project * (using ges_asset_extract (@project);) * * Returns: %TRUE if the project could be save, %FALSE otherwize */ gboolean ges_project_save (GESProject * project, GESTimeline * timeline, const gchar * uri, GESAsset * formatter_asset, gboolean overwrite, GError ** error) { GESAsset *tl_asset; gboolean ret = TRUE; GESFormatter *formatter = NULL; g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (formatter_asset == NULL || g_type_is_a (ges_asset_get_extractable_type (formatter_asset), GES_TYPE_FORMATTER), FALSE); g_return_val_if_fail ((error == NULL || *error == NULL), FALSE); tl_asset = ges_extractable_get_asset (GES_EXTRACTABLE (timeline)); if (tl_asset == NULL && project->priv->uri == NULL) { GESAsset *asset = ges_asset_cache_lookup (GES_TYPE_PROJECT, uri); if (asset) { GST_WARNING_OBJECT (project, "Trying to save project to %s but we already" "have %" GST_PTR_FORMAT " for that uri, can not save", uri, asset); goto out; } GST_DEBUG_OBJECT (project, "Timeline %" GST_PTR_FORMAT " has no asset" " we have no uri set, so setting ourself as asset", timeline); ges_extractable_set_asset (GES_EXTRACTABLE (timeline), GES_ASSET (project)); } else if (tl_asset != GES_ASSET (project)) { GST_WARNING_OBJECT (project, "Timeline %" GST_PTR_FORMAT " not created by this project can not save", timeline); ret = FALSE; goto out; } if (formatter_asset == NULL) formatter_asset = gst_object_ref (ges_formatter_get_default ()); formatter = GES_FORMATTER (ges_asset_extract (formatter_asset, error)); if (formatter == NULL) { GST_WARNING_OBJECT (project, "Could not create the formatter %p %s: %s", formatter_asset, ges_asset_get_id (formatter_asset), (error && *error) ? (*error)->message : "Unknown Error"); ret = FALSE; goto out; } ges_project_add_formatter (project, formatter); ret = ges_formatter_save_to_uri (formatter, timeline, uri, overwrite, error); if (ret && project->priv->uri == NULL) ges_project_set_uri (project, uri); out: if (formatter_asset) gst_object_unref (formatter_asset); ges_project_remove_formatter (project, formatter); return ret; }
/** * ges_layer_add_clip: * @layer: a #GESLayer * @clip: (transfer full): the #GESClip to add. * * Adds the given clip to the layer. Sets the clip's parent, and thus * takes ownership of the clip. * * An clip can only be added to one layer. * * Calling this method will construct and properly set all the media related * elements on @clip. If you need to know when those objects (actually #GESTrackElement) * are constructed, you should connect to the container::child-added signal which * is emited right after those elements are ready to be used. * * Returns: TRUE if the clip was properly added to the layer, or FALSE * if the @layer refuses to add the clip. */ gboolean ges_layer_add_clip (GESLayer * layer, GESClip * clip) { GESAsset *asset; GESLayerPrivate *priv; GESLayer *current_layer; g_return_val_if_fail (GES_IS_LAYER (layer), FALSE); g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); GST_DEBUG_OBJECT (layer, "adding clip:%p", clip); priv = layer->priv; current_layer = ges_clip_get_layer (clip); if (G_UNLIKELY (current_layer)) { GST_WARNING ("Clip %p already belongs to another layer", clip); gst_object_unref (current_layer); return FALSE; } asset = ges_extractable_get_asset (GES_EXTRACTABLE (clip)); if (asset == NULL) { gchar *id; NewAssetUData *mudata = g_slice_new (NewAssetUData); mudata->clip = clip; mudata->layer = layer; GST_DEBUG_OBJECT (layer, "%" GST_PTR_FORMAT " as no reference to any " "assets creating a asset... trying sync", clip); id = ges_extractable_get_id (GES_EXTRACTABLE (clip)); asset = ges_asset_request (G_OBJECT_TYPE (clip), id, NULL); if (asset == NULL) { GESProject *project = layer->timeline ? GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE (layer->timeline))) : NULL; ges_asset_request_async (G_OBJECT_TYPE (clip), id, NULL, (GAsyncReadyCallback) new_asset_cb, mudata); if (project) ges_project_add_loading_asset (project, G_OBJECT_TYPE (clip), id); g_free (id); GST_LOG_OBJECT (layer, "Object added async"); return TRUE; } g_free (id); ges_extractable_set_asset (GES_EXTRACTABLE (clip), asset); g_slice_free (NewAssetUData, mudata); } gst_object_ref_sink (clip); /* Take a reference to the clip and store it stored by start/priority */ priv->clips_start = g_list_insert_sorted (priv->clips_start, clip, (GCompareFunc) element_start_compare); /* Inform the clip it's now in this layer */ ges_clip_set_layer (clip, layer); GST_DEBUG ("current clip priority : %d, Height: %d", _PRIORITY (clip), LAYER_HEIGHT); /* Set the priority. */ if (_PRIORITY (clip) > LAYER_HEIGHT) { GST_WARNING_OBJECT (layer, "%p is out of the layer space, setting its priority to " "%d, setting it to the maximum priority of the layer: %d", clip, _PRIORITY (clip), LAYER_HEIGHT - 1); _set_priority0 (GES_TIMELINE_ELEMENT (clip), LAYER_HEIGHT - 1); } /* If the clip has an acceptable priority, we just let it with its current * priority */ ges_layer_resync_priorities (layer); ges_timeline_element_set_timeline (GES_TIMELINE_ELEMENT (clip), layer->timeline); /* emit 'clip-added' */ g_signal_emit (layer, ges_layer_signals[OBJECT_ADDED], 0, clip); return TRUE; }
void getClips (JsonReader * reader, GESLayer * layer, GESTrackType type, gboolean absolute_paths) { int i; json_reader_read_member (reader, "clips"); g_print ("= clips =\n"); for (i = 0; i < json_reader_count_elements (reader); i++) { json_reader_read_element (reader, i); const char *src = getString (reader, "src"); int start = getInt (reader, "start"); int in = getInt (reader, "in"); int dur = getInt (reader, "dur"); g_print ("Clip: %s (start: %d, in: %d, dur: %d)\n", src, start, in, dur); GESClip *clip; if (is_in_members (reader, "multi") && getBool (reader, "multi")) { g_print ("multi on.\n"); clip = ges_multi_clip_from_path (src, layer, start, in, dur, absolute_paths); } else { const char *path; if (absolute_paths == TRUE) { path = src; } else { path = ges_renderer_get_absolute_path (src); } clip = ges_clip_from_path (path, layer, start, in, dur, type); } GESTimeline *tl = ges_layer_get_timeline (layer); GList *tracks = ges_timeline_get_tracks (tl); GESTrack *trackv = g_list_first (tracks)->data; GESTrack *tracka = g_list_last (tracks)->data; if (is_in_members (reader, "volume")) { double volume = getDouble (reader, "volume"); GESTrackElement *audioElement = ges_clip_find_track_element (clip, tracka, G_TYPE_NONE); if (audioElement != NULL) { ges_track_element_set_child_properties (audioElement, "volume", volume, NULL); } } GESTrackElement *videoElement = ges_clip_find_track_element (clip, trackv, G_TYPE_NONE); if (videoElement != NULL) { if (is_in_members (reader, "x")) { int x = getInt (reader, "x"); ges_track_element_set_child_properties (videoElement, "posx", x, NULL); } if (is_in_members (reader, "y")) { int y = getInt (reader, "y"); ges_track_element_set_child_properties (videoElement, "posy", y, NULL); } if (is_in_members (reader, "alpha")) { gdouble alpha = getDouble (reader, "alpha"); ges_track_element_set_child_properties (videoElement, "alpha", alpha, NULL); } if (is_in_members (reader, "size")) { gdouble size = getDouble (reader, "size"); GESUriClipAsset *asset = GES_URI_CLIP_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (clip))); guint width = ges_asset_get_width (asset); guint height = ges_asset_get_height (asset); if (width != 0 && height != 0) { double dw = width * size; double dh = height * size; g_print ("%dx%d => * %f => %dx%d\n", width, height, size, (int) dw, (int) dh); ges_track_element_set_child_properties (videoElement, "width", (int) dw, "height", (int) dh, NULL); } } if (is_in_members (reader, "effect")) { const char *effect_str = getString (reader, "effect"); if (strcmp (effect_str, "") != 0) { g_print ("Using effect %s", effect_str); GESEffect *effect = ges_effect_new (effect_str); ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (effect)); } } } json_reader_end_element (reader); } json_reader_end_member (reader); }