ges: Implement the ges_timeline_layer_add_asset method
authorThibault Saunier <thibault.saunier@collabora.com>
Mon, 17 Dec 2012 20:05:56 +0000 (17:05 -0300)
committerThibault Saunier <thibault.saunier@collabora.com>
Wed, 19 Dec 2012 21:59:48 +0000 (18:59 -0300)
  + Remove GstDiscoverer related code in GESTimeline as we do not need it anymore
  + Refactor the ges_timeline_layer_add_object method to make sure it is still working as intended

API:
  ges_timeline_layer_add_asset

ges/ges-timeline-layer.c
ges/ges-timeline-layer.h
ges/ges-timeline.c

index d2f248b..53e7b8e 100644 (file)
@@ -59,6 +59,12 @@ struct _GESTimelineLayerPrivate
   gboolean auto_transition;
 };
 
+typedef struct
+{
+  GESTimelineObject *object;
+  GESTimelineLayer *layer;
+} NewAssetUData;
+
 enum
 {
   PROP_0,
@@ -695,6 +701,26 @@ start_calculating_transitions (GESTimelineLayer * layer)
   /* FIXME calculate all the transitions at that time */
 }
 
+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->object);
+
+  if (error) {
+    GST_ERROR ("Asset could not be created for uri");
+  } else {
+    ges_timeline_layer_add_object (udata->layer, udata->object);
+  }
+
+  g_object_unref (asset);
+  g_slice_free (NewAssetUData, udata);
+}
+
 /* Public methods */
 /**
  * ges_timeline_layer_remove_object:
@@ -713,7 +739,7 @@ gboolean
 ges_timeline_layer_remove_object (GESTimelineLayer * layer,
     GESTimelineObject * object)
 {
-  GESTimelineLayer *tl_obj_layer;
+  GESTimelineLayer *current_layer;
   GList *trackobjects, *tmp;
 
   g_return_val_if_fail (GES_IS_TIMELINE_LAYER (layer), FALSE);
@@ -721,16 +747,16 @@ ges_timeline_layer_remove_object (GESTimelineLayer * layer,
 
   GST_DEBUG ("layer:%p, object:%p", layer, object);
 
-  tl_obj_layer = ges_timeline_object_get_layer (object);
-  if (G_UNLIKELY (tl_obj_layer != layer)) {
+  current_layer = ges_timeline_object_get_layer (object);
+  if (G_UNLIKELY (current_layer != layer)) {
     GST_WARNING ("TimelineObject doesn't belong to this layer");
 
-    if (tl_obj_layer != NULL)
-      g_object_unref (tl_obj_layer);
+    if (current_layer != NULL)
+      g_object_unref (current_layer);
 
     return FALSE;
   }
-  g_object_unref (tl_obj_layer);
+  g_object_unref (current_layer);
 
   if (layer->priv->auto_transition && GES_IS_TIMELINE_SOURCE (object)) {
     trackobjects = ges_timeline_object_get_track_objects (object);
@@ -912,24 +938,60 @@ gboolean
 ges_timeline_layer_add_object (GESTimelineLayer * layer,
     GESTimelineObject * object)
 {
-  GESTimelineLayer *tl_obj_layer;
+  GESAsset *asset;
+  GESTimelineLayer *current_layer;
   guint32 maxprio, minprio, prio;
 
-  GST_DEBUG ("layer:%p, object:%p", layer, object);
+  GESTimelineLayerPrivate *priv;
+
+  g_return_val_if_fail (GES_IS_TIMELINE_LAYER (layer), FALSE);
+  g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
 
-  tl_obj_layer = ges_timeline_object_get_layer (object);
+  GST_DEBUG_OBJECT (layer, "adding object:%p", object);
 
-  if (G_UNLIKELY (tl_obj_layer)) {
+  priv = layer->priv;
+  current_layer = ges_timeline_object_get_layer (object);
+
+  if (G_UNLIKELY (current_layer)) {
     GST_WARNING ("TimelineObject %p already belongs to another layer", object);
-    g_object_unref (tl_obj_layer);
+    g_object_unref (current_layer);
+
     return FALSE;
   }
 
+  asset = ges_extractable_get_asset (GES_EXTRACTABLE (object));
+  if (asset == NULL) {
+    gchar *id;
+    NewAssetUData *mudata = g_slice_new (NewAssetUData);
+
+    mudata->object = object;
+    mudata->layer = layer;
+
+    GST_DEBUG_OBJECT (layer, "%" GST_PTR_FORMAT " as no reference to any "
+        "assets creating a asset... trying sync", object);
+
+    id = ges_extractable_get_id (GES_EXTRACTABLE (object));
+    asset = ges_asset_request (G_OBJECT_TYPE (object), id, NULL);
+    if (asset == NULL) {
+      ges_asset_request_async (G_OBJECT_TYPE (object),
+          id, NULL, (GAsyncReadyCallback) new_asset_cb, mudata);
+      g_free (id);
+
+      GST_LOG_OBJECT (layer, "Object added async");
+      return TRUE;
+    }
+    g_free (id);
+
+    ges_extractable_set_asset (GES_EXTRACTABLE (object), asset);
+
+    g_slice_free (NewAssetUData, mudata);
+  }
+
+
   g_object_ref_sink (object);
 
   /* Take a reference to the object and store it stored by start/priority */
-  layer->priv->objects_start =
-      g_list_insert_sorted (layer->priv->objects_start, object,
+  priv->objects_start = g_list_insert_sorted (priv->objects_start, object,
       (GCompareFunc) objects_start_compare);
 
   /* Inform the object it's now in this layer */
@@ -943,15 +1005,17 @@ ges_timeline_layer_add_object (GESTimelineLayer * layer,
   maxprio = layer->max_gnl_priority;
   minprio = layer->min_gnl_priority;
   prio = GES_TIMELINE_OBJECT_PRIORITY (object);
+
   if (minprio + prio > (maxprio)) {
-    GST_WARNING ("%p is out of the layer %p space, setting its priority to "
-        "setting its priority %d to failthe maximum priority of the layer %d",
-        object, layer, prio, maxprio - minprio);
+    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", object, prio,
+        maxprio - minprio);
     ges_timeline_object_set_priority (object, LAYER_HEIGHT - 1);
   }
+
   /* If the object has an acceptable priority, we just let it with its current
    * priority */
-
   ges_timeline_layer_resync_priorities (layer);
 
   /* emit 'object-added' */
@@ -961,6 +1025,54 @@ ges_timeline_layer_add_object (GESTimelineLayer * layer,
 }
 
 /**
+ * ges_timeline_layer_add_asset:
+ * @layer: a #GESTimelineLayer
+ * @asset: The asset to add to
+ * @start: The start value to set on the new #GESTimelineObject
+ * @inpoint: The inpoint value to set on the new #GESTimelineObject
+ * @duration: The duration value to set on the new #GESTimelineObject
+ * @rate: The rate value to set on the new #GESTimelineObject
+ * @track_types: The #GESTrackType to set on the the new #GESTimelineObject
+ *
+ * Creates TimelineObject from asset, adds it to layer and
+ * returns a reference to it.
+ *
+ * Returns: (transfer floating): Created #GESTimelineObject
+*/
+GESTimelineObject *
+ges_timeline_layer_add_asset (GESTimelineLayer * layer,
+    GESAsset * asset, GstClockTime start, GstClockTime inpoint,
+    GstClockTime duration, gdouble rate, GESTrackType track_types)
+{
+  GESTimelineObject *tlobj;
+
+  g_return_val_if_fail (GES_IS_TIMELINE_LAYER (layer), NULL);
+  g_return_val_if_fail (GES_IS_ASSET (asset), NULL);
+  g_return_val_if_fail (g_type_is_a (ges_asset_get_extractable_type
+          (asset), GES_TYPE_TIMELINE_OBJECT), NULL);
+
+
+  GST_DEBUG_OBJECT (layer, "Adding asset: %s", ges_asset_get_id (asset));
+  tlobj = GES_TIMELINE_OBJECT (ges_asset_extract (asset, NULL));
+  ges_timeline_object_set_start (tlobj, start);
+  ges_timeline_object_set_inpoint (tlobj, inpoint);
+  if (track_types != GES_TRACK_TYPE_UNKNOWN)
+    ges_timeline_object_set_supported_formats (tlobj, track_types);
+
+  if (GST_CLOCK_TIME_IS_VALID (duration)) {
+    ges_timeline_object_set_duration (tlobj, duration);
+  }
+
+  if (!ges_timeline_layer_add_object (layer, tlobj)) {
+    gst_object_unref (tlobj);
+
+    return NULL;
+  }
+
+  return tlobj;
+}
+
+/**
  * ges_timeline_layer_new:
  *
  * Creates a new #GESTimelineLayer.
index 990bf3e..abd73e7 100644 (file)
@@ -50,7 +50,7 @@ typedef struct _GESTimelineLayerPrivate GESTimelineLayerPrivate;
  * @timeline: the #GESTimeline where this layer is being used.
  */
 struct _GESTimelineLayer {
-  GInitiallyUnowned parent; 
+  GInitiallyUnowned parent;
 
   /*< public >*/
 
@@ -102,6 +102,14 @@ ges_timeline_layer_get_timeline           (GESTimelineLayer * layer);
 gboolean ges_timeline_layer_add_object    (GESTimelineLayer * layer,
 
                                           GESTimelineObject * object);
+GESTimelineObject * ges_timeline_layer_add_asset   (GESTimelineLayer *layer,
+                                                       GESAsset *asset,
+                                                       GstClockTime start,
+                                                       GstClockTime inpoint,
+                                                       GstClockTime duration,
+                                                       gdouble rate,
+                                                       GESTrackType track_types);
+
 gboolean ges_timeline_layer_remove_object (GESTimelineLayer * layer,
                                           GESTimelineObject * object);
 
index fbdcbae..debe65e 100644 (file)
@@ -117,15 +117,6 @@ struct _GESTimelinePrivate
   /* The duration of the timeline */
   gint64 duration;
 
-  /* discoverer used for virgin sources */
-  GstDiscoverer *discoverer;
-  GList *pendingobjects;
-  /* lock to avoid discovery of objects that will be removed */
-  GMutex pendingobjects_lock;
-
-  /* Whether we are changing state asynchronously or not */
-  gboolean async_pending;
-
   /* Timeline edition modes and snapping management */
   guint64 snapping_distance;
 
@@ -183,13 +174,6 @@ static GstBinClass *parent_class;
 static guint ges_timeline_signals[LAST_SIGNAL] = { 0 };
 
 static gint custom_find_track (TrackPrivate * tr_priv, GESTrack * track);
-static GstStateChangeReturn
-ges_timeline_change_state (GstElement * element, GstStateChange transition);
-static void
-discoverer_finished_cb (GstDiscoverer * discoverer, GESTimeline * timeline);
-static void
-discoverer_discovered_cb (GstDiscoverer * discoverer,
-    GstDiscovererInfo * info, GError * err, GESTimeline * timeline);
 
 /* Internal methods */
 static gboolean
@@ -257,12 +241,6 @@ ges_timeline_dispose (GObject * object)
 {
   GESTimelinePrivate *priv = GES_TIMELINE (object)->priv;
 
-  if (priv->discoverer) {
-    gst_discoverer_stop (priv->discoverer);
-    g_object_unref (priv->discoverer);
-    priv->discoverer = NULL;
-  }
-
   while (priv->layers) {
     GESTimelineLayer *layer = (GESTimelineLayer *) priv->layers->data;
     ges_timeline_remove_layer (GES_TIMELINE (object), layer);
@@ -293,10 +271,6 @@ ges_timeline_dispose (GObject * object)
 static void
 ges_timeline_finalize (GObject * object)
 {
-  GESTimeline *timeline = GES_TIMELINE (object);
-
-  g_mutex_clear (&timeline->priv->pendingobjects_lock);
-
   G_OBJECT_CLASS (ges_timeline_parent_class)->finalize (object);
 }
 
@@ -304,14 +278,11 @@ static void
 ges_timeline_class_init (GESTimelineClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESTimelinePrivate));
 
   parent_class = g_type_class_peek_parent (klass);
 
-  element_class->change_state = ges_timeline_change_state;
-
   object_class->get_property = ges_timeline_get_property;
   object_class->set_property = ges_timeline_set_property;
   object_class->dispose = ges_timeline_dispose;
@@ -489,15 +460,6 @@ ges_timeline_init (GESTimeline * self)
       (GDestroyNotify) _destroy_obj_iters);
   priv->starts_ends = g_sequence_new (g_free);
   priv->tracksources = g_sequence_new (g_object_unref);
-
-  g_mutex_init (&priv->pendingobjects_lock);
-  /* New discoverer with a 15s timeout */
-  priv->discoverer = gst_discoverer_new (15 * GST_SECOND, NULL);
-  g_signal_connect (priv->discoverer, "finished",
-      G_CALLBACK (discoverer_finished_cb), self);
-  g_signal_connect (priv->discoverer, "discovered",
-      G_CALLBACK (discoverer_discovered_cb), self);
-  gst_discoverer_start (priv->discoverer);
 }
 
 /* Private methods */
@@ -1442,169 +1404,6 @@ add_object_to_tracks (GESTimeline * timeline, GESTimelineObject * object)
 }
 
 static void
-do_async_start (GESTimeline * timeline)
-{
-  GstMessage *message;
-  GList *tmp;
-
-  timeline->priv->async_pending = TRUE;
-
-  /* Freeze state of tracks */
-  for (tmp = timeline->priv->tracks; tmp; tmp = tmp->next) {
-    TrackPrivate *tr_priv = (TrackPrivate *) tmp->data;
-    gst_element_set_locked_state ((GstElement *) tr_priv->track, TRUE);
-  }
-
-  message = gst_message_new_async_start (GST_OBJECT_CAST (timeline));
-  parent_class->handle_message (GST_BIN_CAST (timeline), message);
-}
-
-static void
-do_async_done (GESTimeline * timeline)
-{
-  GstMessage *message;
-
-  if (timeline->priv->async_pending) {
-    GList *tmp;
-    /* Unfreeze state of tracks */
-    for (tmp = timeline->priv->tracks; tmp; tmp = tmp->next) {
-      TrackPrivate *tr_priv = (TrackPrivate *) tmp->data;
-      gst_element_set_locked_state ((GstElement *) tr_priv->track, FALSE);
-      gst_element_sync_state_with_parent ((GstElement *) tr_priv->track);
-    }
-
-    GST_DEBUG_OBJECT (timeline, "Emitting async-done");
-    message = gst_message_new_async_done (GST_OBJECT_CAST (timeline), FALSE);
-    parent_class->handle_message (GST_BIN_CAST (timeline), message);
-
-    timeline->priv->async_pending = FALSE;
-  }
-}
-
-/* Callbacks  */
-static void
-discoverer_finished_cb (GstDiscoverer * discoverer, GESTimeline * timeline)
-{
-  do_async_done (timeline);
-}
-
-static void
-discoverer_discovered_cb (GstDiscoverer * discoverer,
-    GstDiscovererInfo * info, GError * err, GESTimeline * timeline)
-{
-  GList *tmp;
-  GList *stream_list;
-  GESTimelineObject *tlobj;
-  GESTrackType tfs_supportedformats;
-
-  gboolean found = FALSE;
-  gboolean is_image = FALSE;
-  GESTimelineFileSource *tfs = NULL;
-  GESTimelinePrivate *priv = timeline->priv;
-  const gchar *uri = gst_discoverer_info_get_uri (info);
-
-  GES_TIMELINE_PENDINGOBJS_LOCK (timeline);
-
-  /* Find corresponding TimelineFileSource in the sources */
-  for (tmp = priv->pendingobjects; tmp; tmp = tmp->next) {
-    tfs = (GESTimelineFileSource *) tmp->data;
-
-    if (!g_strcmp0 (ges_timeline_filesource_get_uri (tfs), uri)) {
-      found = TRUE;
-      break;
-    }
-  }
-
-  if (!found) {
-    GST_WARNING ("Discovered %s, that seems not to be in the list of sources"
-        "to discover", uri);
-    GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-    return;
-  }
-
-  if (err) {
-    GError *propagate_error = NULL;
-
-    priv->pendingobjects = g_list_delete_link (priv->pendingobjects, tmp);
-    GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-    GST_WARNING ("Error while discovering %s: %s", uri, err->message);
-
-    g_propagate_error (&propagate_error, err);
-    g_signal_emit (timeline, ges_timeline_signals[DISCOVERY_ERROR], 0, tfs,
-        propagate_error);
-
-    return;
-  }
-
-  /* Everything went fine... let's do our job! */
-  GST_DEBUG ("Discovered uri %s", uri);
-
-  /* The timeline file source will be updated with discovered information
-   * so it needs to not be finalized during this process */
-  g_object_ref (tfs);
-
-  /* Remove object from list */
-  priv->pendingobjects = g_list_delete_link (priv->pendingobjects, tmp);
-  GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-
-  /* FIXME : Handle errors in discovery */
-  stream_list = gst_discoverer_info_get_stream_list (info);
-
-  tfs_supportedformats = ges_timeline_filesource_get_supported_formats (tfs);
-  if (tfs_supportedformats != GES_TRACK_TYPE_UNKNOWN)
-    goto check_image;
-
-  /* Update timelinefilesource properties based on info */
-  for (tmp = stream_list; tmp; tmp = tmp->next) {
-    GstDiscovererStreamInfo *sinf = (GstDiscovererStreamInfo *) tmp->data;
-
-    if (GST_IS_DISCOVERER_AUDIO_INFO (sinf)) {
-      tfs_supportedformats |= GES_TRACK_TYPE_AUDIO;
-      ges_timeline_filesource_set_supported_formats (tfs, tfs_supportedformats);
-    } else if (GST_IS_DISCOVERER_VIDEO_INFO (sinf)) {
-      tfs_supportedformats |= GES_TRACK_TYPE_VIDEO;
-      ges_timeline_filesource_set_supported_formats (tfs, tfs_supportedformats);
-      if (gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *)
-              sinf)) {
-        tfs_supportedformats |= GES_TRACK_TYPE_AUDIO;
-        ges_timeline_filesource_set_supported_formats (tfs,
-            tfs_supportedformats);
-        is_image = TRUE;
-      }
-    }
-  }
-
-  if (stream_list)
-    gst_discoverer_stream_info_list_free (stream_list);
-
-check_image:
-
-  tlobj = GES_TIMELINE_OBJECT (tfs);
-  if (is_image) {
-    /* don't set max-duration on still images */
-    g_object_set (tfs, "is_image", (gboolean) TRUE, NULL);
-  } else {
-    GstClockTime file_duration, tlobj_max_duration;
-
-    /* Properly set duration informations from the discovery */
-    file_duration = gst_discoverer_info_get_duration (info);
-    tlobj_max_duration = ges_timeline_object_get_max_duration (tlobj);
-
-    if (tlobj_max_duration == G_MAXUINT64)
-      ges_timeline_object_set_max_duration (tlobj, file_duration);
-
-    if (GST_CLOCK_TIME_IS_VALID (tlobj->duration) == FALSE)
-      ges_timeline_object_set_duration (tlobj, file_duration);
-  }
-
-  /* Continue the processing on tfs */
-  add_object_to_tracks (timeline, tlobj);
-
-  /* Remove the ref as the timeline file source is no longer needed here */
-  g_object_unref (tfs);
-}
-
-static void
 layer_object_added_cb (GESTimelineLayer * layer, GESTimelineObject * object,
     GESTimeline * timeline)
 {
@@ -1616,37 +1415,8 @@ layer_object_added_cb (GESTimelineLayer * layer, GESTimelineObject * object,
   }
 
   GST_DEBUG ("New TimelineObject %p added to layer %p", object, layer);
-
-  if (GES_IS_TIMELINE_FILE_SOURCE (object)) {
-    GESTimelineFileSource *tfs = GES_TIMELINE_FILE_SOURCE (object);
-    GESTrackType tfs_supportedformats =
-        ges_timeline_filesource_get_supported_formats (tfs);
-    guint64 tfs_maxdur = ges_timeline_filesource_get_max_duration (tfs);
-    const gchar *tfs_uri;
-
-    /* Send the filesource to the discoverer if:
-     * * it doesn't have specified supported formats
-     * * OR it doesn't have a specified max-duration
-     * * OR it doesn't have a valid duration  */
-
-    if (tfs_supportedformats == GES_TRACK_TYPE_UNKNOWN ||
-        tfs_maxdur == GST_CLOCK_TIME_NONE || object->duration == 0) {
-      GST_LOG ("Incomplete TimelineFileSource, discovering it");
-      tfs_uri = ges_timeline_filesource_get_uri (tfs);
-
-      GES_TIMELINE_PENDINGOBJS_LOCK (timeline);
-      timeline->priv->pendingobjects =
-          g_list_append (timeline->priv->pendingobjects, object);
-      GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-
-      gst_discoverer_discover_uri_async (timeline->priv->discoverer, tfs_uri);
-    } else
-      add_object_to_tracks (timeline, object);
-  } else {
-    add_object_to_tracks (timeline, object);
-  }
-
-  GST_DEBUG ("done");
+  add_object_to_tracks (timeline, object);
+  GST_DEBUG ("Done");
 }
 
 static void
@@ -1693,16 +1463,6 @@ layer_object_removed_cb (GESTimelineLayer * layer, GESTimelineObject * object,
 
   g_list_free (trackobjects);
 
-  /* if the object is a timeline file source that has not yet been discovered,
-   * it no longer needs to be discovered so remove it from the pendingobjects
-   * list if it belongs to this layer */
-  if (GES_IS_TIMELINE_FILE_SOURCE (object)) {
-    GES_TIMELINE_PENDINGOBJS_LOCK (timeline);
-    timeline->priv->pendingobjects =
-        g_list_remove_all (timeline->priv->pendingobjects, object);
-    GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-  }
-
   GST_DEBUG ("Done");
 }
 
@@ -1835,51 +1595,6 @@ pad_removed_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
   tr_priv->pad = NULL;
 }
 
-
-/* GstElement Virtual methods */
-static GstStateChangeReturn
-ges_timeline_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GESTimeline *timeline = GES_TIMELINE (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      GES_TIMELINE_PENDINGOBJS_LOCK (timeline);
-      if (timeline->priv->pendingobjects) {
-        GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-        do_async_start (timeline);
-        ret = GST_STATE_CHANGE_ASYNC;
-      } else {
-        GES_TIMELINE_PENDINGOBJS_UNLOCK (timeline);
-      }
-      break;
-    default:
-      break;
-  }
-
-  {
-    GstStateChangeReturn bret;
-
-    bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-    if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) {
-      do_async_done (timeline);
-      ret = bret;
-    }
-  }
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      do_async_done (timeline);
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-
-}
-
 /**** API *****/
 /**
  * ges_timeline_new:
@@ -2247,7 +1962,6 @@ ges_timeline_remove_track (GESTimeline * timeline, GESTrack * track)
   }
 
   /* set track state to NULL */
-
   gst_element_set_state (GST_ELEMENT (track), GST_STATE_NULL);
 
   gst_object_unref (track);