ges-uri-asset.c 19.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* GStreamer Editing Services
 *
 * Copyright (C) 2012 Thibault Saunier <thibault.saunier@collabora.com>
 * Copyright (C) 2012 Volodymyr Rudyi <vladimir.rudoy@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
/**
22
 * SECTION: gesuriclipasset
23
 * @short_description: A GESAsset subclass specialized in GESUriClip extraction
24
 *
25
 * The #GESUriClipAsset is a special #GESAsset that lets you handle
26
27
28
29
 * the media file to use inside the GStreamer Editing Services. It has APIs that
 * let you get information about the medias. Also, the tags found in the media file are
 * set as Metadatas of the Asser.
 */
30
#include <errno.h>
31
32
33
#include <gst/pbutils/pbutils.h>
#include "ges.h"
#include "ges-internal.h"
34
#include "ges-track-element-asset.h"
35
36

static GHashTable *parent_newparent_table = NULL;
37

38
39
40
41
42
43
44
static void
initable_iface_init (GInitableIface * initable_iface)
{
  /*  We can not iniate synchronously */
  initable_iface->init = NULL;
}

45
G_DEFINE_TYPE_WITH_CODE (GESUriClipAsset, ges_uri_clip_asset,
46
    GES_TYPE_CLIP_ASSET,
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));

/* TODO: We should monitor files here, and add some way of reporting changes
 * to user
 */
enum
{
  PROP_0,
  PROP_DURATION,
  PROP_LAST
};
static GParamSpec *properties[PROP_LAST];

static void discoverer_discovered_cb (GstDiscoverer * discoverer,
    GstDiscovererInfo * info, GError * err, gpointer user_data);

63
struct _GESUriClipAssetPrivate
64
65
66
67
{
  GstDiscovererInfo *info;
  GstClockTime duration;
  gboolean is_image;
68
69
70
71

  GList *asset_trackfilesources;
};

72
struct _GESUriSourceAssetPrivate
73
74
{
  GstDiscovererStreamInfo *sinfo;
75
  GESUriClipAsset *parent_asset;
76
77

  const gchar *uri;
78
79
80
81
};


static void
82
ges_uri_clip_asset_get_property (GObject * object, guint property_id,
83
84
    GValue * value, GParamSpec * pspec)
{
85
  GESUriClipAssetPrivate *priv = GES_URI_CLIP_ASSET (object)->priv;
86
87
88
89
90
91
92
93
94
95
96

  switch (property_id) {
    case PROP_DURATION:
      g_value_set_uint64 (value, priv->duration);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  }
}

static void
97
ges_uri_clip_asset_set_property (GObject * object, guint property_id,
98
99
    const GValue * value, GParamSpec * pspec)
{
100
  GESUriClipAssetPrivate *priv = GES_URI_CLIP_ASSET (object)->priv;
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

  switch (property_id) {
    case PROP_DURATION:
      priv->duration = g_value_get_uint64 (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  }
}

static GESAssetLoadingReturn
_start_loading (GESAsset * asset, GError ** error)
{
  gboolean ret;
  const gchar *uri;
116
  GESUriClipAssetClass *class = GES_URI_CLIP_ASSET_GET_CLASS (asset);
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

  GST_DEBUG ("Started loading %p", asset);

  uri = ges_asset_get_id (asset);

  ret = gst_discoverer_discover_uri_async (class->discoverer, uri);
  if (ret)
    return GES_ASSET_LOADING_ASYNC;

  return GES_ASSET_LOADING_ERROR;
}

static gboolean
_request_id_update (GESAsset * self, gchar ** proposed_new_id, GError * error)
{
  if (error->domain == GST_RESOURCE_ERROR &&
133
134
      (error->code == GST_RESOURCE_ERROR_NOT_FOUND ||
          error->code == GST_RESOURCE_ERROR_OPEN_READ)) {
135
136
137
138
139
140
141
142
143
144
145
146
    const gchar *uri = ges_asset_get_id (self);
    GFile *parent, *file = g_file_new_for_uri (uri);

    /* Check if we have the new parent in cache */
    parent = g_file_get_parent (file);
    if (parent) {
      GFile *new_parent = g_hash_table_lookup (parent_newparent_table, parent);

      if (new_parent) {
        gchar *basename = g_file_get_basename (file);
        GFile *new_file = g_file_get_child (new_parent, basename);

147
        /* FIXME Handle the GCancellable */
148
        if (g_file_query_exists (new_file, NULL)) {
149
150
151
152
          *proposed_new_id = g_file_get_uri (new_file);
          GST_DEBUG_OBJECT (self, "Proposing path: %s as proxy",
              *proposed_new_id);
        }
153

154
        gst_object_unref (new_file);
155
156
        g_free (basename);
      }
157
      gst_object_unref (parent);
158
159
    }

160
    gst_object_unref (file);
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

    return TRUE;
  }

  return FALSE;
}

static void
_asset_proxied (GESAsset * self, const gchar * new_uri)
{
  const gchar *uri = ges_asset_get_id (self);
  GFile *parent, *new_parent, *new_file = g_file_new_for_uri (new_uri),
      *file = g_file_new_for_uri (uri);

  parent = g_file_get_parent (file);
  new_parent = g_file_get_parent (new_file);
  g_hash_table_insert (parent_newparent_table, parent, new_parent);
178
179
  gst_object_unref (file);
  gst_object_unref (new_file);
180
181
182
}

static void
183
ges_uri_clip_asset_class_init (GESUriClipAssetClass * klass)
184
{
185
186
  GstClockTime timeout;
  const gchar *timeout_str;
187
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
188
  g_type_class_add_private (klass, sizeof (GESUriClipAssetPrivate));
189

190
191
  object_class->get_property = ges_uri_clip_asset_get_property;
  object_class->set_property = ges_uri_clip_asset_set_property;
192
193
194
195
196
197
198

  GES_ASSET_CLASS (klass)->start_loading = _start_loading;
  GES_ASSET_CLASS (klass)->request_id_update = _request_id_update;
  GES_ASSET_CLASS (klass)->inform_proxy = _asset_proxied;


  /**
199
   * GESUriClipAsset:duration:
200
201
202
203
204
205
206
207
208
   *
   * The duration (in nanoseconds) of the media file
   */
  properties[PROP_DURATION] =
      g_param_spec_uint64 ("duration", "Duration", "The duration to use", 0,
      G_MAXUINT64, GST_CLOCK_TIME_NONE, G_PARAM_READWRITE);
  g_object_class_install_property (object_class, PROP_DURATION,
      properties[PROP_DURATION]);

209
210
211
212
213
214
215
216
  errno = 0;
  timeout_str = g_getenv ("GES_DISCOVERY_TIMEOUT");
  if (timeout_str)
    timeout = g_ascii_strtod (timeout_str, NULL) * GST_SECOND;
  else
    errno = 10;

  if (errno)
217
    timeout = 60 * GST_SECOND;
218
219
220

  klass->discoverer = gst_discoverer_new (timeout, NULL);
  klass->sync_discoverer = gst_discoverer_new (timeout, NULL);
221
222
223
224
225
226
227
  g_signal_connect (klass->discoverer, "discovered",
      G_CALLBACK (discoverer_discovered_cb), NULL);

  /* We just start the discoverer and let it live */
  gst_discoverer_start (klass->discoverer);
  if (parent_newparent_table == NULL) {
    parent_newparent_table = g_hash_table_new_full (g_file_hash,
228
        (GEqualFunc) g_file_equal, gst_object_unref, gst_object_unref);
229
230
231
232
  }
}

static void
233
ges_uri_clip_asset_init (GESUriClipAsset * self)
234
{
235
  GESUriClipAssetPrivate *priv;
236
237

  priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
238
      GES_TYPE_URI_CLIP_ASSET, GESUriClipAssetPrivate);
239
240
241
242
243
244

  priv->info = NULL;
  priv->duration = GST_CLOCK_TIME_NONE;
  priv->is_image = FALSE;
}

245
static void
246
_create_uri_source_asset (GESUriClipAsset * asset,
247
248
249
    GstDiscovererStreamInfo * sinfo, GESTrackType type)
{
  GESAsset *tck_filesource_asset;
250
  GESUriSourceAssetPrivate *priv_tckasset;
251
  GESUriClipAssetPrivate *priv = asset->priv;
252
253
254
255
256
257
258
259
260
  gchar *stream_id =
      g_strdup (gst_discoverer_stream_info_get_stream_id (sinfo));

  if (stream_id == NULL) {
    GST_WARNING ("No stream ID found, using the pointer instead");

    stream_id = g_strdup_printf ("%i", GPOINTER_TO_INT (sinfo));
  }

261
262
263
264
265
266
  if (type == GES_TRACK_TYPE_VIDEO)
    tck_filesource_asset = ges_asset_request (GES_TYPE_VIDEO_URI_SOURCE,
        stream_id, NULL);
  else
    tck_filesource_asset = ges_asset_request (GES_TYPE_AUDIO_URI_SOURCE,
        stream_id, NULL);
267
268
  g_free (stream_id);

269
  priv_tckasset = GES_URI_SOURCE_ASSET (tck_filesource_asset)->priv;
270
  priv_tckasset->uri = ges_asset_get_id (GES_ASSET (asset));
271
  priv_tckasset->sinfo = gst_object_ref (sinfo);
272
  priv_tckasset->parent_asset = asset;
273
  ges_track_element_asset_set_track_type (GES_TRACK_ELEMENT_ASSET
274
      (tck_filesource_asset), type);
275
276
277
278
279

  priv->asset_trackfilesources = g_list_append (priv->asset_trackfilesources,
      gst_object_ref (tck_filesource_asset));
}

280
static void
281
ges_uri_clip_asset_set_info (GESUriClipAsset * self, GstDiscovererInfo * info)
282
283
284
285
{
  GList *tmp, *stream_list;

  GESTrackType supportedformats = GES_TRACK_TYPE_UNKNOWN;
286
  GESUriClipAssetPrivate *priv = GES_URI_CLIP_ASSET (self)->priv;
287
288
289
290

  /* Extract infos from the GstDiscovererInfo */
  stream_list = gst_discoverer_info_get_stream_list (info);
  for (tmp = stream_list; tmp; tmp = tmp->next) {
291
    GESTrackType type = GES_TRACK_TYPE_UNKNOWN;
292
293
294
295
296
297
298
299
    GstDiscovererStreamInfo *sinf = (GstDiscovererStreamInfo *) tmp->data;

    if (GST_IS_DISCOVERER_AUDIO_INFO (sinf)) {
      if (supportedformats == GES_TRACK_TYPE_UNKNOWN)
        supportedformats = GES_TRACK_TYPE_AUDIO;
      else
        supportedformats |= GES_TRACK_TYPE_AUDIO;

300
      type = GES_TRACK_TYPE_AUDIO;
301
302
303
304
305
306
    } else if (GST_IS_DISCOVERER_VIDEO_INFO (sinf)) {
      if (supportedformats == GES_TRACK_TYPE_UNKNOWN)
        supportedformats = GES_TRACK_TYPE_VIDEO;
      else
        supportedformats |= GES_TRACK_TYPE_VIDEO;
      if (gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *)
307
              sinf))
308
        priv->is_image = TRUE;
309
310
311
      type = GES_TRACK_TYPE_VIDEO;
    }

312
    GST_DEBUG_OBJECT (self, "Creating GESUriSourceAsset for stream: %s",
313
        gst_discoverer_stream_info_get_stream_id (sinf));
314
    _create_uri_source_asset (self, sinf, type);
315
  }
316
  ges_clip_asset_set_supported_formats (GES_CLIP_ASSET
317
      (self), supportedformats);
318
319
320
321
322
323
324
325

  if (stream_list)
    gst_discoverer_stream_info_list_free (stream_list);

  if (priv->is_image == FALSE)
    priv->duration = gst_discoverer_info_get_duration (info);
  /* else we keep #GST_CLOCK_TIME_NONE */

326
  priv->info = gst_object_ref (info);
327
328
329
330
331
332
333
334
}

static void
_set_meta_foreach (const GstTagList * tags, const gchar * tag,
    GESMetaContainer * container)
{
  GValue value = { 0 };

335
336
337
338
339
340
  if (gst_tag_list_copy_value (&value, tags, tag)) {
    ges_meta_container_set_meta (container, tag, &value);
    g_value_unset (&value);
  } else {
    GST_INFO ("Could not set metadata: %s", tag);
  }
341
342
343
344
345
346
347
348
349
}

static void
discoverer_discovered_cb (GstDiscoverer * discoverer,
    GstDiscovererInfo * info, GError * err, gpointer user_data)
{
  const GstTagList *tags;

  const gchar *uri = gst_discoverer_info_get_uri (info);
350
351
  GESUriClipAsset *mfs =
      GES_URI_CLIP_ASSET (ges_asset_cache_lookup (GES_TYPE_URI_CLIP, uri));
352
353
354
355
356

  tags = gst_discoverer_info_get_tags (info);
  if (tags)
    gst_tag_list_foreach (tags, (GstTagForeachFunc) _set_meta_foreach, mfs);

357
  if (gst_discoverer_info_get_result (info) == GST_DISCOVERER_OK) {
358
    ges_uri_clip_asset_set_info (mfs, info);
359
360
361
362
363
364
  } else if (!err) {
    err = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
        "Stream %s discovering failed (error code: %d)",
        uri, gst_discoverer_info_get_result (info));
  }

365
  ges_asset_cache_set_loaded (GES_TYPE_URI_CLIP, uri, err);
366
367
368
369
}

/* API implementation */
/**
370
 * ges_uri_clip_asset_get_info:
371
372
373
374
375
376
377
 * @self: Target asset
 *
 * Gets #GstDiscovererInfo about the file
 *
 * Returns: (transfer none): #GstDiscovererInfo of specified asset
 */
GstDiscovererInfo *
378
ges_uri_clip_asset_get_info (const GESUriClipAsset * self)
379
{
380
381
  g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (self), NULL);

382
383
384
385
  return self->priv->info;
}

/**
386
387
 * ges_uri_clip_asset_get_duration:
 * @self: a #GESUriClipAsset
388
389
390
391
392
393
 *
 * Gets duration of the file represented by @self
 *
 * Returns: The duration of @self
 */
GstClockTime
394
ges_uri_clip_asset_get_duration (GESUriClipAsset * self)
395
{
396
  g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (self), GST_CLOCK_TIME_NONE);
397
398
399
400
401

  return self->priv->duration;
}

/**
402
 * ges_uri_clip_asset_is_image:
403
 * @self: a #indent: Standard input:311: Error:Unexpected end of file
404
GESUriClipAsset
405
406
407
408
409
410
 *
 * Gets Whether the file represented by @self is an image or not
 *
 * Returns: Whether the file represented by @self is an image or not
 */
gboolean
411
ges_uri_clip_asset_is_image (GESUriClipAsset * self)
412
{
413
  g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (self), FALSE);
414
415
416
417
418

  return self->priv->is_image;
}

/**
419
420
 * ges_uri_clip_asset_new:
 * @uri: The URI of the file for which to create a #GESUriClipAsset
421
422
423
424
 * @cancellable: optional %GCancellable object, %NULL to ignore.
 * @callback: (scope async): a #GAsyncReadyCallback to call when the initialization is finished
 * @user_data: The user data to pass when @callback is called
 *
425
 * Creates a #GESUriClipAsset for @uri
426
 *
427
 * Example of request of a GESUriClipAsset:
428
429
430
431
432
433
 * |[
 * // The request callback
 * static void
 * filesource_asset_loaded_cb (GESAsset * source, GAsyncResult * res, gpointer user_data)
 * {
 *   GError *error = NULL;
434
 *   GESUriClipAsset *filesource_asset;
435
 *
436
 *   filesource_asset = GES_URI_CLIP_ASSET (ges_asset_request_finish (res, &error));
437
438
439
 *   if (filesource_asset) {
 *    g_print ("The file: %s is usable as a FileSource, it is%s an image and lasts %" GST_TIME_FORMAT,
 *        ges_asset_get_id (GES_ASSET (filesource_asset))
440
441
 *        ges_uri_clip_asset_is_image (filesource_asset) ? "" : " not",
 *        GST_TIME_ARGS (ges_uri_clip_asset_get_duration (filesource_asset));
442
443
444
445
446
 *   } else {
 *    g_print ("The file: %s is *not* usable as a FileSource because: %s",
 *        ges_asset_get_id (source), error->message);
 *   }
 *
447
 *   gst_object_unref (mfs);
448
449
450
 * }
 *
 * // The request:
451
 * ges_uri_clip_asset_new (uri, (GAsyncReadyCallback) filesource_asset_loaded_cb, user_data);
452
453
454
 * ]|
 */
void
455
ges_uri_clip_asset_new (const gchar * uri, GCancellable * cancellable,
456
457
    GAsyncReadyCallback callback, gpointer user_data)
{
458
  ges_asset_request_async (GES_TYPE_URI_CLIP, uri, cancellable,
459
460
461
      callback, user_data);
}

462
/**
463
 * ges_uri_clip_asset_request_sync:
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
464
465
 * @uri: The URI of the file for which to create a #GESUriClipAsset.
 * You can also use multi file uris for #GESMultiFileSource.
466
467
468
469
470
 * @error: (allow-none): An error to be set in case something wrong happens or %NULL
 *
 * Creates a #GESUriClipAsset for @uri syncronously. You should avoid
 * to use it in application, and rather create #GESUriClipAsset asynchronously
 *
471
 * Returns: (transfer none): A reference to the requested asset or %NULL if an error happend
472
473
474
475
476
477
478
479
 */
GESUriClipAsset *
ges_uri_clip_asset_request_sync (const gchar * uri, GError ** error)
{
  GError *lerror = NULL;
  GstDiscovererInfo *info;
  GstDiscoverer *discoverer;
  GESUriClipAsset *asset;
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
480
  gchar *first_file, *first_file_uri;
481
482
483
484
485
486
487

  asset = GES_URI_CLIP_ASSET (ges_asset_request (GES_TYPE_URI_CLIP, uri,
          &lerror));

  if (asset)
    return asset;

488
489
  if (lerror && lerror->domain == GES_ERROR &&
      lerror->code == GES_ERROR_ASSET_WRONG_ID) {
490
491
492
493
494
495
496
497
    g_propagate_error (error, lerror);

    return NULL;
  }

  asset = g_object_new (GES_TYPE_URI_CLIP_ASSET, "id", uri,
      "extractable-type", GES_TYPE_URI_CLIP, NULL);
  discoverer = GES_URI_CLIP_ASSET_GET_CLASS (asset)->sync_discoverer;
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513

  if (g_str_has_prefix (uri, GES_MULTI_FILE_URI_PREFIX)) {
    GESMultiFileURI *uri_data;

    uri_data = ges_multi_file_uri_new (uri);
    first_file = g_strdup_printf (uri_data->location, uri_data->start);
    first_file_uri = gst_filename_to_uri (first_file, &lerror);
    info = gst_discoverer_discover_uri (discoverer, first_file_uri, &lerror);
    GST_DEBUG ("Got multifile uri. Discovering first file %s", first_file_uri);
    g_free (uri_data);
    g_free (first_file_uri);
    g_free (first_file);
  } else {
    info = gst_discoverer_discover_uri (discoverer, uri, &lerror);
  }

514
515
516
517
  ges_asset_cache_put (gst_object_ref (asset), NULL);
  ges_uri_clip_asset_set_info (asset, info);
  ges_asset_cache_set_loaded (GES_TYPE_URI_CLIP, uri, lerror);

518
519
520
521
522
523
524
525
526
527
528
  if (info == NULL || lerror != NULL) {
    gst_object_unref (asset);
    if (lerror)
      g_propagate_error (error, lerror);

    return NULL;
  }

  return asset;
}

529
/**
530
 * ges_uri_clip_asset_class_set_timeout:
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
531
 * @klass: The #GESUriClipAssetClass on which to set the discoverer timeout
532
533
 * @timeout: The timeout to set
 *
534
 * Sets the timeout of #GESUriClipAsset loading
535
536
 */
void
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
537
ges_uri_clip_asset_class_set_timeout (GESUriClipAssetClass * klass,
538
539
    GstClockTime timeout)
{
Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
540
  g_return_if_fail (GES_IS_URI_CLIP_ASSET_CLASS (klass));
541

Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
542
543
  g_object_set (klass->discoverer, "timeout", timeout, NULL);
  g_object_set (klass->sync_discoverer, "timeout", timeout, NULL);
544
}
545
546

/**
547
548
 * ges_uri_clip_asset_get_stream_assets:
 * @self: A #GESUriClipAsset
549
 *
550
 * Get the GESUriSourceAsset @self containes
551
 *
552
553
 * Returns: (transfer none) (element-type GESUriSourceAsset): a
 * #GList of #GESUriSourceAsset
554
555
 */
const GList *
556
ges_uri_clip_asset_get_stream_assets (GESUriClipAsset * self)
557
{
558
  g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (self), FALSE);
559
560
561
562
563

  return self->priv->asset_trackfilesources;
}

/*****************************************************************
564
 *            GESUriSourceAsset implementation             *
565
566
 *****************************************************************/
/**
567
 * SECTION: gesurisourceasset
568
 * @short_description: A GESAsset subclass specialized in GESUriSource extraction
569
570
 *
 * NOTE: You should never request such a #GESAsset as they will be created automatically
571
 * by #GESUriClipAsset-s.
572
573
 */

574
G_DEFINE_TYPE (GESUriSourceAsset, ges_uri_source_asset,
575
    GES_TYPE_TRACK_ELEMENT_ASSET);
576
577
578
579

static GESExtractable *
_extract (GESAsset * asset, GError ** error)
{
580
  GESTrackElement *trackelement;
581
  GESUriSourceAssetPrivate *priv = GES_URI_SOURCE_ASSET (asset)->priv;
582
583
584
585
586
587
588
589
590
591
592
593
594

  if (GST_IS_DISCOVERER_STREAM_INFO (priv->sinfo) == FALSE) {
    GST_WARNING_OBJECT (asset, "Can not extract as no strean info set");

    return NULL;
  }

  if (priv->uri == NULL) {
    GST_WARNING_OBJECT (asset, "Can not extract as no uri set");

    return NULL;
  }

Lubosz Sarnecki's avatar
Lubosz Sarnecki committed
595
596
597
598
599
  if (g_str_has_prefix (priv->uri, GES_MULTI_FILE_URI_PREFIX)) {
    trackelement =
        GES_TRACK_ELEMENT (ges_multi_file_source_new (g_strdup (priv->uri)));
  } else if (GST_IS_DISCOVERER_VIDEO_INFO (priv->sinfo)
      && gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *)
600
601
602
          priv->sinfo))
    trackelement =
        GES_TRACK_ELEMENT (ges_image_source_new (g_strdup (priv->uri)));
603
604
605
  else if (GST_IS_DISCOVERER_VIDEO_INFO (priv->sinfo))
    trackelement =
        GES_TRACK_ELEMENT (ges_video_uri_source_new (g_strdup (priv->uri)));
606
607
  else
    trackelement =
608
609
        GES_TRACK_ELEMENT (ges_audio_uri_source_new (g_strdup (priv->uri)));

610
611
  ges_track_element_set_track_type (trackelement,
      ges_track_element_asset_get_track_type (GES_TRACK_ELEMENT_ASSET (asset)));
612

613
  return GES_EXTRACTABLE (trackelement);
614
615
616
}

static void
617
ges_uri_source_asset_class_init (GESUriSourceAssetClass * klass)
618
{
619
  g_type_class_add_private (klass, sizeof (GESUriSourceAssetPrivate));
620
621
622
623
624

  GES_ASSET_CLASS (klass)->extract = _extract;
}

static void
625
ges_uri_source_asset_init (GESUriSourceAsset * self)
626
{
627
  GESUriSourceAssetPrivate *priv;
628
629

  priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
630
      GES_TYPE_URI_SOURCE_ASSET, GESUriSourceAssetPrivate);
631
632
633
634
635
636

  priv->sinfo = NULL;
  priv->parent_asset = NULL;
  priv->uri = NULL;
}

Thibault Saunier's avatar
Thibault Saunier committed
637
/**
638
 * ges_uri_source_asset_get_stream_info:
639
 * @asset: A #GESUriClipAsset
Thibault Saunier's avatar
Thibault Saunier committed
640
641
642
 *
 * Get the #GstDiscovererStreamInfo user by @asset
 *
643
 * Returns: (transfer none): a #GESUriClipAsset
Thibault Saunier's avatar
Thibault Saunier committed
644
 */
645
GstDiscovererStreamInfo *
646
ges_uri_source_asset_get_stream_info (GESUriSourceAsset * asset)
647
{
648
  g_return_val_if_fail (GES_IS_URI_SOURCE_ASSET (asset), NULL);
649
650
651
652
653

  return asset->priv->sinfo;
}

const gchar *
654
ges_uri_source_asset_get_stream_uri (GESUriSourceAsset * asset)
655
{
656
  g_return_val_if_fail (GES_IS_URI_SOURCE_ASSET (asset), NULL);
657
658
659
660
661

  return asset->priv->uri;
}

/**
662
 * ges_uri_source_asset_get_filesource_asset:
663
 * @asset: A #GESUriClipAsset
664
 *
665
 * Get the #GESUriClipAsset @self is contained in
666
 *
667
 * Returns: a #GESUriClipAsset
668
 */
669
const GESUriClipAsset *
670
ges_uri_source_asset_get_filesource_asset (GESUriSourceAsset * asset)
671
{
672
  g_return_val_if_fail (GES_IS_URI_SOURCE_ASSET (asset), NULL);
673
674
675

  return asset->priv->parent_asset;
}