mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
Implement asset proxying support
API: ges_asset_set_proxy ges_asset_get_proxy ges_asset_list_proxies ges_asset_get_proxy_target Differential Revision: https://phabricator.freedesktop.org/D504
This commit is contained in:
parent
081c285e22
commit
fa512ecdba
10 changed files with 362 additions and 45 deletions
|
@ -1079,6 +1079,10 @@ ges_asset_request_finish
|
|||
ges_asset_extract
|
||||
ges_asset_get_error
|
||||
ges_list_assets
|
||||
ges_asset_set_proxy
|
||||
ges_asset_list_proxies
|
||||
ges_asset_get_proxy_target
|
||||
ges_asset_get_proxy
|
||||
<SUBSECTION Standard>
|
||||
GESAssetPrivate
|
||||
GES_ASSET
|
||||
|
|
214
ges/ges-asset.c
214
ges/ges-asset.c
|
@ -96,6 +96,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_TYPE,
|
||||
PROP_ID,
|
||||
PROP_PROXY,
|
||||
PROP_PROXY_TARGET,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -115,11 +117,14 @@ struct _GESAssetPrivate
|
|||
GESAssetState state;
|
||||
GType extractable_type;
|
||||
|
||||
/* When a asset is proxied, instanciating it will
|
||||
/* When an asset is proxied, instanciating it will
|
||||
* return the asset it points to */
|
||||
char *proxied_asset_id;
|
||||
|
||||
/* The error that accured when a asset has been initialized with error */
|
||||
GList *proxies;
|
||||
GESAsset *proxy_target;
|
||||
|
||||
/* The error that accured when an asset has been initialized with error */
|
||||
GError *error;
|
||||
};
|
||||
|
||||
|
@ -314,6 +319,12 @@ ges_asset_get_property (GObject * object, guint property_id,
|
|||
case PROP_ID:
|
||||
g_value_set_string (value, asset->priv->id);
|
||||
break;
|
||||
case PROP_PROXY:
|
||||
g_value_set_object (value, ges_asset_get_proxy (asset));
|
||||
break;
|
||||
case PROP_PROXY_TARGET:
|
||||
g_value_set_object (value, ges_asset_get_proxy_target (asset));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
@ -333,6 +344,12 @@ ges_asset_set_property (GObject * object, guint property_id,
|
|||
case PROP_ID:
|
||||
asset->priv->id = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_PROXY:
|
||||
ges_asset_set_proxy (asset, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_PROXY_TARGET:
|
||||
ges_asset_set_proxy (g_value_get_object (value), asset);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
@ -377,6 +394,14 @@ ges_asset_class_init (GESAssetClass * klass)
|
|||
"The unic identifier of the asset", NULL,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
|
||||
_properties[PROP_PROXY] =
|
||||
g_param_spec_object ("proxy", "Proxy",
|
||||
"The asset default proxy.", GES_TYPE_ASSET, G_PARAM_READWRITE);
|
||||
|
||||
_properties[PROP_PROXY_TARGET] =
|
||||
g_param_spec_object ("proxy-target", "Proxy target",
|
||||
"The target of a proxy asset.", GES_TYPE_ASSET, G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, _properties);
|
||||
|
||||
klass->start_loading = ges_asset_start_loading_default;
|
||||
|
@ -593,9 +618,10 @@ ges_asset_request_id_update (GESAsset * asset, gchar ** proposed_id,
|
|||
}
|
||||
|
||||
gboolean
|
||||
ges_asset_set_proxy (GESAsset * asset, const gchar * new_id)
|
||||
ges_asset_try_proxy (GESAsset * asset, const gchar * new_id)
|
||||
{
|
||||
GESAssetClass *class;
|
||||
|
||||
if (g_strcmp0 (asset->priv->id, new_id) == 0) {
|
||||
GST_WARNING_OBJECT (asset, "Trying to proxy to itself (%s),"
|
||||
" NOT possible", new_id);
|
||||
|
@ -609,9 +635,7 @@ ges_asset_set_proxy (GESAsset * asset, const gchar * new_id)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (asset->priv->proxied_asset_id)
|
||||
g_free (asset->priv->proxied_asset_id);
|
||||
|
||||
g_free (asset->priv->proxied_asset_id);
|
||||
asset->priv->state = ASSET_PROXIED;
|
||||
asset->priv->proxied_asset_id = g_strdup (new_id);
|
||||
|
||||
|
@ -619,10 +643,160 @@ ges_asset_set_proxy (GESAsset * asset, const gchar * new_id)
|
|||
if (class->inform_proxy)
|
||||
GES_ASSET_GET_CLASS (asset)->inform_proxy (asset, new_id);
|
||||
|
||||
GST_DEBUG_OBJECT (asset, "Now proxied to %s", new_id);
|
||||
GST_DEBUG_OBJECT (asset, "Trying to proxy to %s", new_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_lookup_proxied_asset (const gchar * id, GESAssetCacheEntry * entry,
|
||||
const gchar * asset_id)
|
||||
{
|
||||
return !g_strcmp0 (asset_id, entry->asset->priv->proxied_asset_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_asset_set_proxy:
|
||||
* @asset: The #GESAsset to set proxy on
|
||||
* @proxy: (allow-none): The #GESAsset that should be used as default proxy for @asset or
|
||||
* %NULL if you want to use the currently set proxy. Note that an asset can proxy one and only
|
||||
* one other asset.
|
||||
*
|
||||
* A proxying asset is an asset that can substitue the real @asset. For example if you
|
||||
* have a full HD #GESUriClipAsset you might want to set a lower resolution (HD version
|
||||
* of the same file) as proxy. Note that when an asset is proxied, calling
|
||||
* #ges_asset_request will actually return the proxy asset.
|
||||
*
|
||||
* Returns: The list of proxies @asset has. Note that the default asset to be
|
||||
* used is always the first in that list.
|
||||
*/
|
||||
gboolean
|
||||
ges_asset_set_proxy (GESAsset * asset, GESAsset * proxy)
|
||||
{
|
||||
g_return_val_if_fail (asset == NULL || GES_IS_ASSET (asset), FALSE);
|
||||
g_return_val_if_fail (proxy == NULL || GES_IS_ASSET (proxy), FALSE);
|
||||
g_return_val_if_fail (asset != proxy, FALSE);
|
||||
|
||||
if (!proxy) {
|
||||
if (asset->priv->error) {
|
||||
GST_ERROR_OBJECT (asset,
|
||||
"Proxy was loaded with error (%s), it should not be 'unproxied'",
|
||||
asset->priv->error->message);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (asset->priv->proxies) {
|
||||
GESAsset *old_proxy = GES_ASSET (asset->priv->proxies->data);
|
||||
|
||||
GES_ASSET (asset->priv->proxies->data)->priv->proxy_target = NULL;
|
||||
g_object_notify_by_pspec (G_OBJECT (old_proxy),
|
||||
_properties[PROP_PROXY_TARGET]);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (asset, "%s not proxied anymore", asset->priv->id);
|
||||
asset->priv->state = ASSET_INITIALIZED;
|
||||
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (asset == NULL) {
|
||||
GHashTable *entries_table;
|
||||
GESAssetCacheEntry *entry;
|
||||
|
||||
entries_table = g_hash_table_lookup (type_entries_table,
|
||||
_extractable_type_name (proxy->priv->extractable_type));
|
||||
entry = g_hash_table_find (entries_table, (GHRFunc) _lookup_proxied_asset,
|
||||
(gpointer) ges_asset_get_id (proxy));
|
||||
|
||||
if (!entry) {
|
||||
GST_DEBUG_OBJECT (asset, "Not proxying any asset");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
asset = entry->asset;
|
||||
while (asset->priv->proxies)
|
||||
asset = asset->priv->proxies->data;
|
||||
}
|
||||
|
||||
if (proxy->priv->proxy_target) {
|
||||
GST_ERROR_OBJECT (asset,
|
||||
"Trying to use %s as a proxy, but it is already proxying %s",
|
||||
proxy->priv->id, proxy->priv->proxy_target->priv->id);
|
||||
}
|
||||
|
||||
if (g_list_find (proxy->priv->proxies, asset)) {
|
||||
GST_ERROR_OBJECT (asset, "Trying to setup a circular proxying dependency!");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_list_find (asset->priv->proxies, proxy)) {
|
||||
GST_INFO_OBJECT (asset,
|
||||
"%" GST_PTR_FORMAT " already marked as proxy, moving to first", proxy);
|
||||
GES_ASSET (asset->priv->proxies->data)->priv->proxy_target = NULL;
|
||||
asset->priv->proxies = g_list_remove (asset->priv->proxies, proxy);
|
||||
}
|
||||
|
||||
GST_INFO ("%s is now proxied by %s", asset->priv->id, proxy->priv->id);
|
||||
asset->priv->proxies = g_list_prepend (asset->priv->proxies, proxy);
|
||||
proxy->priv->proxy_target = asset;
|
||||
g_object_notify_by_pspec (G_OBJECT (proxy), _properties[PROP_PROXY_TARGET]);
|
||||
|
||||
asset->priv->state = ASSET_PROXIED;
|
||||
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_asset_list_proxies:
|
||||
* @asset: The #GESAsset to get proxies from
|
||||
*
|
||||
* Returns: The list of proxies @asset has. Note that the default asset to be
|
||||
* used is always the first in that list.
|
||||
*/
|
||||
GList *
|
||||
ges_asset_list_proxies (GESAsset * asset)
|
||||
{
|
||||
g_return_val_if_fail (GES_IS_ASSET (asset), NULL);
|
||||
|
||||
return asset->priv->proxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_asset_get_proxy:
|
||||
* @asset: The #GESAsset to get currenlty used proxy
|
||||
*
|
||||
* Returns: (transfer none): The proxy in use for @asset
|
||||
*/
|
||||
GESAsset *
|
||||
ges_asset_get_proxy (GESAsset * asset)
|
||||
{
|
||||
g_return_val_if_fail (GES_IS_ASSET (asset), NULL);
|
||||
|
||||
if (asset->priv->state == ASSET_PROXIED && asset->priv->proxies) {
|
||||
return asset->priv->proxies->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_asset_get_proxy_target:
|
||||
* @proxy: The #GESAsset from which to get the the asset it proxies.
|
||||
*
|
||||
* Returns: (transfer none): The #GESAsset that is proxied by @proxy
|
||||
*/
|
||||
GESAsset *
|
||||
ges_asset_get_proxy_target (GESAsset * proxy)
|
||||
{
|
||||
g_return_val_if_fail (GES_IS_ASSET (proxy), NULL);
|
||||
|
||||
return proxy->priv->proxy_target;
|
||||
}
|
||||
|
||||
/* Caution, this method should be used in rare cases (ie: for the project
|
||||
* as we can change its ID from a useless one to a proper URI). In most
|
||||
* cases you want to update the ID creating a proxy
|
||||
|
@ -751,19 +925,21 @@ ges_asset_request (GType extractable_type, const gchar * id, GError ** error)
|
|||
asset = NULL;
|
||||
goto done;
|
||||
case ASSET_PROXIED:
|
||||
asset =
|
||||
ges_asset_cache_lookup (asset->priv->extractable_type,
|
||||
asset->priv->proxied_asset_id);
|
||||
if (asset == NULL) {
|
||||
GST_ERROR ("Asset against a asset we do not"
|
||||
if (asset->priv->proxies == NULL) {
|
||||
GST_ERROR ("Proxied against an asset we do not"
|
||||
" have in cache, something massively screwed");
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
asset = asset->priv->proxies->data;
|
||||
while (ges_asset_get_proxy (asset))
|
||||
asset = ges_asset_get_proxy (asset);
|
||||
|
||||
break;
|
||||
case ASSET_INITIALIZED_WITH_ERROR:
|
||||
GST_WARNING_OBJECT (asset, "Initialized with error, not returning");
|
||||
if (asset->priv->error)
|
||||
if (asset->priv->error && error)
|
||||
*error = g_error_copy (asset->priv->error);
|
||||
asset = NULL;
|
||||
goto done;
|
||||
|
@ -866,7 +1042,7 @@ ges_asset_request_async (GType extractable_type,
|
|||
real_id = g_strdup (id);
|
||||
}
|
||||
|
||||
/* Check if we already have a asset for this ID */
|
||||
/* Check if we already have an asset for this ID */
|
||||
asset = ges_asset_cache_lookup (extractable_type, real_id);
|
||||
if (asset) {
|
||||
GTask *task = g_task_new (asset, NULL, callback, user_data);
|
||||
|
@ -892,12 +1068,12 @@ ges_asset_request_async (GType extractable_type,
|
|||
|
||||
goto done;
|
||||
case ASSET_PROXIED:
|
||||
asset =
|
||||
ges_asset_cache_lookup (asset->priv->extractable_type,
|
||||
asset->priv->proxied_asset_id);
|
||||
asset = ges_asset_get_proxy (asset);
|
||||
|
||||
if (asset == NULL) {
|
||||
GST_ERROR ("Asset proxied against a asset we do not"
|
||||
" have in cache, something massively screwed");
|
||||
GST_ERROR ("Asset %s proxied against an asset (%s) we do not"
|
||||
" have in cache, something massively screwed",
|
||||
asset->priv->id, asset->priv->proxied_asset_id);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,10 @@ struct _GESAssetClass
|
|||
/* Let subclasses know that we proxied an asset */
|
||||
void (*inform_proxy) (GESAsset *self,
|
||||
const gchar *proxy_id);
|
||||
|
||||
void (*proxied) (GESAsset *self,
|
||||
GESAsset *proxy);
|
||||
|
||||
/* Ask subclasses for a new ID for @self when the asset failed loading
|
||||
* This function returns %FALSE when the ID could be updated or %TRUE
|
||||
* otherwize */
|
||||
|
@ -100,5 +104,11 @@ GESExtractable * ges_asset_extract (GESAsset * self,
|
|||
GError **error);
|
||||
GList * ges_list_assets (GType filter);
|
||||
|
||||
|
||||
gboolean ges_asset_set_proxy (GESAsset *asset, GESAsset *proxy);
|
||||
GList * ges_asset_list_proxies (GESAsset *asset);
|
||||
GESAsset * ges_asset_get_proxy_target(GESAsset *proxy);
|
||||
GESAsset * ges_asset_get_proxy (GESAsset *asset);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* _GES_ASSET */
|
||||
|
|
|
@ -100,6 +100,7 @@ typedef struct PendingAsset
|
|||
GESFormatter *formatter;
|
||||
gchar *metadatas;
|
||||
GstStructure *properties;
|
||||
gchar *proxy_id;
|
||||
} PendingAsset;
|
||||
|
||||
struct _GESBaseXmlFormatterPrivate
|
||||
|
@ -467,6 +468,7 @@ _add_all_groups (GESFormatter * self)
|
|||
static void
|
||||
_loading_done (GESFormatter * self)
|
||||
{
|
||||
GList *assets, *tmp;
|
||||
GESBaseXmlFormatterPrivate *priv = GES_BASE_XML_FORMATTER (self)->priv;
|
||||
|
||||
_add_all_groups (self);
|
||||
|
@ -478,6 +480,13 @@ _loading_done (GESFormatter * self)
|
|||
ges_timeline_set_auto_transition (self->timeline,
|
||||
priv->timeline_auto_transition);
|
||||
|
||||
/* Go over all assets and make sure that all proxies we were 'trying' to set are finally
|
||||
* properly set */
|
||||
assets = ges_project_list_assets (self->project, GES_TYPE_EXTRACTABLE);
|
||||
for (tmp = assets; tmp; tmp = tmp->next) {
|
||||
ges_asset_set_proxy (NULL, tmp->data);
|
||||
}
|
||||
|
||||
g_hash_table_foreach (priv->layers, (GHFunc) _set_auto_transition, NULL);
|
||||
ges_project_set_loaded (self->project, self);
|
||||
}
|
||||
|
@ -623,8 +632,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
|
|||
static void
|
||||
_free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
|
||||
{
|
||||
if (passet->metadatas)
|
||||
g_free (passet->metadatas);
|
||||
g_free (passet->metadatas);
|
||||
g_free (passet->proxy_id);
|
||||
if (passet->properties)
|
||||
gst_structure_free (passet->properties);
|
||||
|
||||
|
@ -722,6 +731,13 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (passet->proxy_id) {
|
||||
/* We set the URI to be used as a proxy,
|
||||
* this will finally be set as the proxy when we
|
||||
* are done loading all assets */
|
||||
ges_asset_try_proxy (asset, passet->proxy_id);
|
||||
}
|
||||
|
||||
/* now that we have the GESAsset, we create the GESClips */
|
||||
pendings = g_hash_table_lookup (priv->assetid_pendingclips, id);
|
||||
GST_DEBUG_OBJECT (self, "Asset created with ID %s, now creating pending "
|
||||
|
@ -825,7 +841,7 @@ _create_profile (GESBaseXmlFormatter * self,
|
|||
void
|
||||
ges_base_xml_formatter_add_asset (GESBaseXmlFormatter * self,
|
||||
const gchar * id, GType extractable_type, GstStructure * properties,
|
||||
const gchar * metadatas, GError ** error)
|
||||
const gchar * metadatas, const gchar * proxy_id, GError ** error)
|
||||
{
|
||||
PendingAsset *passet;
|
||||
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
|
||||
|
@ -835,6 +851,7 @@ ges_base_xml_formatter_add_asset (GESBaseXmlFormatter * self,
|
|||
|
||||
passet = g_slice_new0 (PendingAsset);
|
||||
passet->metadatas = g_strdup (metadatas);
|
||||
passet->proxy_id = g_strdup (proxy_id);
|
||||
passet->formatter = gst_object_ref (self);
|
||||
if (properties)
|
||||
passet->properties = gst_structure_copy (properties);
|
||||
|
|
|
@ -143,7 +143,7 @@ GESAsset*
|
|||
ges_asset_cache_lookup(GType extractable_type, const gchar * id);
|
||||
|
||||
gboolean
|
||||
ges_asset_set_proxy (GESAsset *asset, const gchar *new_id);
|
||||
ges_asset_try_proxy (GESAsset *asset, const gchar *new_id);
|
||||
|
||||
G_GNUC_INTERNAL gboolean
|
||||
ges_asset_request_id_update (GESAsset *asset, gchar **proposed_id,
|
||||
|
@ -224,6 +224,7 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_asset (GESBaseXmlFormatte
|
|||
GType extractable_type,
|
||||
GstStructure *properties,
|
||||
const gchar *metadatas,
|
||||
const gchar *proxy_id,
|
||||
GError **error);
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_layer (GESBaseXmlFormatter *self,
|
||||
GType extractable_type,
|
||||
|
|
|
@ -595,7 +595,7 @@ ges_project_try_updating_id (GESProject * project, GESAsset * asset,
|
|||
|
||||
if (new_id) {
|
||||
GST_DEBUG_OBJECT (project, "new id found: %s", new_id);
|
||||
if (!ges_asset_set_proxy (asset, new_id)) {
|
||||
if (!ges_asset_try_proxy (asset, new_id)) {
|
||||
g_free (new_id);
|
||||
new_id = NULL;
|
||||
}
|
||||
|
@ -633,6 +633,7 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, GESProject * project)
|
|||
return;
|
||||
}
|
||||
|
||||
ges_asset_set_proxy (NULL, asset);
|
||||
ges_project_add_asset (project, asset);
|
||||
if (asset)
|
||||
gst_object_unref (asset);
|
||||
|
@ -766,6 +767,10 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
|
|||
if (asset) {
|
||||
retry = FALSE;
|
||||
|
||||
if ((!g_hash_table_lookup (project->priv->assets,
|
||||
ges_asset_get_id (asset))))
|
||||
g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, asset);
|
||||
|
||||
if (possible_id) {
|
||||
g_free (possible_id);
|
||||
ges_uri_assets_validate_uri (id);
|
||||
|
@ -776,6 +781,9 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
|
|||
GESAsset *tmpasset;
|
||||
|
||||
tmpasset = ges_asset_cache_lookup (extractable_type, id);
|
||||
g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, tmpasset);
|
||||
g_signal_emit (project, _signals[ERROR_LOADING_ASSET], 0, *error, id,
|
||||
extractable_type);
|
||||
possible_id = ges_project_try_updating_id (project, tmpasset, *error);
|
||||
|
||||
if (possible_id == NULL)
|
||||
|
@ -788,6 +796,9 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
|
|||
}
|
||||
}
|
||||
|
||||
if (!ges_asset_get_proxy_target (asset))
|
||||
ges_asset_set_proxy (NULL, asset);
|
||||
|
||||
ges_project_add_asset (project, asset);
|
||||
|
||||
return asset;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "ges-image-source.h"
|
||||
#include "ges-audio-test-source.h"
|
||||
#include "ges-multi-file-source.h"
|
||||
#include "ges-layer.h"
|
||||
|
||||
static void ges_extractable_interface_init (GESExtractableInterface * iface);
|
||||
|
||||
|
@ -260,13 +261,19 @@ extractable_get_id (GESExtractable * self)
|
|||
return g_strdup (GES_URI_CLIP (self)->priv->uri);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
extractable_set_asset (GESExtractable * self, GESAsset * asset)
|
||||
{
|
||||
gboolean res = TRUE;
|
||||
GESUriClip *uriclip = GES_URI_CLIP (self);
|
||||
GESUriClipAsset *filesource_asset = GES_URI_CLIP_ASSET (asset);
|
||||
GESUriClipAsset *filesource_asset;
|
||||
GESClip *clip = GES_CLIP (self);
|
||||
GESLayer *layer = ges_clip_get_layer (clip);
|
||||
GList *tmp;
|
||||
|
||||
g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (asset), FALSE);
|
||||
|
||||
filesource_asset = GES_URI_CLIP_ASSET (asset);
|
||||
if (GST_CLOCK_TIME_IS_VALID (GES_TIMELINE_ELEMENT_DURATION (clip)) == FALSE)
|
||||
_set_duration0 (GES_TIMELINE_ELEMENT (uriclip),
|
||||
ges_uri_clip_asset_get_duration (filesource_asset));
|
||||
|
@ -277,13 +284,35 @@ extractable_set_asset (GESExtractable * self, GESAsset * asset)
|
|||
ges_uri_clip_asset_is_image (filesource_asset));
|
||||
|
||||
if (ges_clip_get_supported_formats (clip) == GES_TRACK_TYPE_UNKNOWN) {
|
||||
|
||||
ges_clip_set_supported_formats (clip,
|
||||
ges_clip_asset_get_supported_formats
|
||||
(GES_CLIP_ASSET (filesource_asset)));
|
||||
ges_clip_asset_get_supported_formats (GES_CLIP_ASSET
|
||||
(filesource_asset)));
|
||||
}
|
||||
|
||||
GES_TIMELINE_ELEMENT (uriclip)->asset = asset;
|
||||
|
||||
if (layer) {
|
||||
for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) {
|
||||
if (GES_IS_SOURCE (tmp->data)) {
|
||||
GESTrack *track = ges_track_element_get_track (tmp->data);
|
||||
|
||||
ges_track_remove_element (track, tmp->data);
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_ref (clip);
|
||||
ges_layer_remove_clip (layer, clip);
|
||||
res = ges_layer_add_clip (layer, clip);
|
||||
gst_object_unref (clip);
|
||||
gst_object_unref (layer);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
g_free (uriclip->priv->uri);
|
||||
uriclip->priv->uri = g_strdup (ges_asset_get_id (asset));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -293,7 +322,9 @@ ges_extractable_interface_init (GESExtractableInterface * iface)
|
|||
iface->check_id = (GESExtractableCheckId) extractable_check_id;
|
||||
iface->get_parameters_from_id = extractable_get_parameters_from_id;
|
||||
iface->get_id = extractable_get_id;
|
||||
iface->set_asset = extractable_set_asset;
|
||||
iface->get_id = extractable_get_id;
|
||||
iface->can_update_asset = TRUE;
|
||||
iface->set_asset_full = extractable_set_asset;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
G_DEFINE_TYPE (GESXmlFormatter, ges_xml_formatter, GES_TYPE_BASE_XML_FORMATTER);
|
||||
|
||||
#define API_VERSION 0
|
||||
#define MINOR_VERSION 2
|
||||
#define VERSION 0.2
|
||||
#define MINOR_VERSION 3
|
||||
#define VERSION 0.3
|
||||
|
||||
#define COLLECT_STR_OPT (G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL)
|
||||
|
||||
|
@ -272,14 +272,15 @@ _parse_asset (GMarkupParseContext * context, const gchar * element_name,
|
|||
{
|
||||
GType extractable_type;
|
||||
const gchar *id, *extractable_type_name, *metadatas = NULL, *properties =
|
||||
NULL;
|
||||
NULL, *proxy_id = NULL;
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||
attribute_values, error, G_MARKUP_COLLECT_STRING, "id", &id,
|
||||
G_MARKUP_COLLECT_STRING, "extractable-type-name",
|
||||
&extractable_type_name,
|
||||
COLLECT_STR_OPT, "properties", &properties,
|
||||
COLLECT_STR_OPT, "metadatas", &metadatas, G_MARKUP_COLLECT_INVALID))
|
||||
COLLECT_STR_OPT, "metadatas", &metadatas,
|
||||
COLLECT_STR_OPT, "proxy-id", &proxy_id, G_MARKUP_COLLECT_INVALID))
|
||||
return;
|
||||
|
||||
extractable_type = g_type_from_name (extractable_type_name);
|
||||
|
@ -299,7 +300,7 @@ _parse_asset (GMarkupParseContext * context, const gchar * element_name,
|
|||
props = gst_structure_from_string (properties, NULL);
|
||||
|
||||
ges_base_xml_formatter_add_asset (GES_BASE_XML_FORMATTER (self), id,
|
||||
extractable_type, props, metadatas, error);
|
||||
extractable_type, props, metadatas, proxy_id, error);
|
||||
if (props)
|
||||
gst_structure_free (props);
|
||||
}
|
||||
|
@ -910,10 +911,10 @@ _serialize_properties (GObject * object, const gchar * fieldname, ...)
|
|||
}
|
||||
|
||||
static inline void
|
||||
_save_assets (GString * str, GESProject * project)
|
||||
_save_assets (GESXmlFormatter * self, GString * str, GESProject * project)
|
||||
{
|
||||
char *properties, *metas;
|
||||
GESAsset *asset;
|
||||
GESAsset *asset, *proxy;
|
||||
GList *assets, *tmp;
|
||||
|
||||
assets = ges_project_list_assets (project, GES_TYPE_EXTRACTABLE);
|
||||
|
@ -923,10 +924,27 @@ _save_assets (GString * str, GESProject * project)
|
|||
metas = ges_meta_container_metas_to_string (GES_META_CONTAINER (asset));
|
||||
append_escaped (str,
|
||||
g_markup_printf_escaped
|
||||
(" <asset id='%s' extractable-type-name='%s' properties='%s' metadatas='%s' />\n",
|
||||
(" <asset id='%s' extractable-type-name='%s' properties='%s' metadatas='%s' ",
|
||||
ges_asset_get_id (asset),
|
||||
g_type_name (ges_asset_get_extractable_type (asset)), properties,
|
||||
metas));
|
||||
|
||||
/*TODO Save the whole list of proxies */
|
||||
proxy = ges_asset_get_proxy (asset);
|
||||
if (proxy) {
|
||||
append_escaped (str, g_markup_printf_escaped (" proxy-id='%s' ",
|
||||
ges_asset_get_id (proxy)));
|
||||
|
||||
if (!g_list_find (assets, proxy)) {
|
||||
assets = g_list_append (assets, gst_object_ref (proxy));
|
||||
|
||||
if (!tmp->next)
|
||||
tmp->next = g_list_last (assets);
|
||||
}
|
||||
|
||||
self->priv->min_version = MAX (self->priv->min_version, 3);
|
||||
}
|
||||
g_string_append (str, "/>\n");
|
||||
g_free (properties);
|
||||
g_free (metas);
|
||||
}
|
||||
|
@ -1433,6 +1451,7 @@ _save (GESFormatter * formatter, GESTimeline * timeline, GError ** error)
|
|||
|
||||
gchar *projstr = NULL, *version;
|
||||
gchar *properties = NULL, *metas = NULL;
|
||||
GESXmlFormatter *self = GES_XML_FORMATTER (formatter);
|
||||
GESXmlFormatterPrivate *priv;
|
||||
|
||||
|
||||
|
@ -1455,10 +1474,10 @@ _save (GESFormatter * formatter, GESTimeline * timeline, GError ** error)
|
|||
g_string_append (str, " </encoding-profiles>\n");
|
||||
|
||||
g_string_append (str, " <ressources>\n");
|
||||
_save_assets (str, project);
|
||||
_save_assets (self, str, project);
|
||||
g_string_append (str, " </ressources>\n");
|
||||
|
||||
_save_timeline (GES_XML_FORMATTER (formatter), str, timeline);
|
||||
_save_timeline (self, str, timeline);
|
||||
g_string_append (str, "</project>\n</ges>");
|
||||
|
||||
projstr = g_strdup_printf ("<ges version='%i.%i'>\n", API_VERSION,
|
||||
|
|
|
@ -35,6 +35,7 @@ SUPPRESSIONS = $(top_srcdir)/common/gst.supp # $(srcdir)/gst-plugins-bad.supp
|
|||
clean-local: clean-local-check
|
||||
|
||||
check_PROGRAMS = \
|
||||
ges/asset \
|
||||
ges/backgroundsource\
|
||||
ges/basic \
|
||||
ges/layer \
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* GStreamer Editing Services
|
||||
*
|
||||
* Copyright (C) 2012 Volodymyr Rudyi <vladimir.rudoy@gmail.com>
|
||||
* Copyright (C) 2015 Thibault Saunier <tsaunier@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -18,8 +19,9 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "../../../ges/ges-internal.h"
|
||||
#include "test-utils.h"
|
||||
#undef GST_CAT_DEFAULT
|
||||
#include "../../../ges/ges-internal.h"
|
||||
#include <ges/ges.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
|
@ -53,7 +55,7 @@ GST_START_TEST (test_basic)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_change_asset)
|
||||
GST_START_TEST (test_transition_change_asset)
|
||||
{
|
||||
gchar *id;
|
||||
GESAsset *a;
|
||||
|
@ -96,6 +98,43 @@ GST_START_TEST (test_change_asset)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_uri_clip_change_asset)
|
||||
{
|
||||
GESAsset *asset, *asset1;
|
||||
GESExtractable *extractable;
|
||||
GESLayer *layer = ges_layer_new ();
|
||||
gchar *uri = ges_test_file_uri ("audio_video.ogg");
|
||||
gchar *uri1 = ges_test_file_uri ("audio_only.ogg");
|
||||
GESTimeline *timeline = ges_timeline_new_audio_video ();
|
||||
|
||||
ges_timeline_add_layer (timeline, layer);
|
||||
|
||||
gst_init (NULL, NULL);
|
||||
ges_init ();
|
||||
|
||||
asset = GES_ASSET (ges_uri_clip_asset_request_sync (uri, NULL));
|
||||
|
||||
fail_unless (GES_IS_ASSET (asset));
|
||||
fail_unless_equals_string (ges_asset_get_id (asset), uri);
|
||||
|
||||
extractable = GES_EXTRACTABLE (ges_layer_add_asset (layer,
|
||||
asset, 0, 0, GST_CLOCK_TIME_NONE, GES_TRACK_TYPE_UNKNOWN));
|
||||
fail_unless (ges_extractable_get_asset (extractable) == asset);
|
||||
gst_object_unref (asset);
|
||||
|
||||
/* Now try to set the a and see if the vtype is properly updated */
|
||||
asset1 = GES_ASSET (ges_uri_clip_asset_request_sync (uri1, NULL));
|
||||
fail_unless_equals_int (g_list_length (GES_CONTAINER_CHILDREN (extractable)),
|
||||
2);
|
||||
fail_unless (ges_extractable_set_asset (extractable, asset1));
|
||||
fail_unless_equals_int (g_list_length (GES_CONTAINER_CHILDREN (extractable)),
|
||||
1);
|
||||
|
||||
gst_object_unref (extractable);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_list_asset)
|
||||
{
|
||||
GList *assets;
|
||||
|
@ -128,7 +167,8 @@ GST_START_TEST (test_proxy_asset)
|
|||
nothing = ges_asset_cache_lookup (GES_TYPE_EFFECT, "nothing");
|
||||
fail_unless (nothing != NULL);
|
||||
|
||||
fail_unless (ges_asset_set_proxy (nothing, "identity"));
|
||||
fail_unless (ges_asset_try_proxy (nothing, "identity"));
|
||||
fail_unless (ges_asset_set_proxy (NULL, identity));
|
||||
|
||||
nothing_at_all = ges_asset_request (GES_TYPE_EFFECT, "nothing_at_all", NULL);
|
||||
fail_if (nothing_at_all);
|
||||
|
@ -137,7 +177,13 @@ GST_START_TEST (test_proxy_asset)
|
|||
fail_unless (nothing_at_all != NULL);
|
||||
|
||||
/* Now we proxy nothing_at_all to nothing which is itself proxied to identity */
|
||||
fail_unless (ges_asset_set_proxy (nothing_at_all, "nothing"));
|
||||
fail_unless (ges_asset_try_proxy (nothing_at_all, "nothing"));
|
||||
fail_unless (ges_asset_set_proxy (NULL, nothing));
|
||||
fail_unless_equals_int (g_list_length (ges_asset_list_proxies
|
||||
(nothing_at_all)), 1);
|
||||
|
||||
fail_unless_equals_pointer (ges_asset_get_proxy_target (nothing),
|
||||
nothing_at_all);
|
||||
|
||||
/* If we request nothing_at_all we should get the good proxied identity */
|
||||
nothing_at_all = ges_asset_request (GES_TYPE_EFFECT, "nothing_at_all", NULL);
|
||||
|
@ -161,7 +207,8 @@ ges_suite (void)
|
|||
/* Must be first until we implement deinit */
|
||||
tcase_add_test (tc_chain, test_list_asset);
|
||||
tcase_add_test (tc_chain, test_basic);
|
||||
tcase_add_test (tc_chain, test_change_asset);
|
||||
tcase_add_test (tc_chain, test_transition_change_asset);
|
||||
tcase_add_test (tc_chain, test_uri_clip_change_asset);
|
||||
tcase_add_test (tc_chain, test_proxy_asset);
|
||||
|
||||
return s;
|
||||
|
|
Loading…
Reference in a new issue