gst/playback/: Add sink padtemplate to decodebin.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 18 Oct 2004 13:40:48 +0000 (13:40 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 18 Oct 2004 13:40:48 +0000 (13:40 +0000)
Original commit message from CVS:
* gst/playback/gstdecodebin.c: (gst_decode_bin_class_init),
(gst_decode_bin_init), (find_compatibles), (close_pad_link),
(try_to_link_1), (no_more_pads), (close_link), (type_found):
* gst/playback/gstplaybasebin.c: (gen_preroll_element),
(remove_prerolls), (unknown_type), (add_element_stream),
(new_decoded_pad), (setup_source), (gst_play_base_bin_add_element),
(gst_play_base_bin_remove_element),
(gst_play_base_bin_link_stream):
* gst/playback/gstplaybin.c: (gen_video_element),
(gen_vis_element), (remove_sinks), (setup_sinks):
* gst/playback/gststreaminfo.c: (gst_stream_type_get_type),
(gst_stream_info_get_type), (gst_stream_info_class_init),
(gst_stream_info_init), (gst_stream_info_new),
(gst_stream_info_dispose), (stream_info_mute_pad),
(gst_stream_info_set_property), (gst_stream_info_get_property):
* gst/playback/gststreaminfo.h:
Add sink padtemplate to decodebin.
Added some more comments.
Make queue size configurable in playbasebin.
Added possibility to use elements as sinks (ex cdaudio).

ChangeLog
gst/playback/README
gst/playback/gstdecodebin.c
gst/playback/gstplaybasebin.c
gst/playback/gstplaybin.c
gst/playback/gststreaminfo.c
gst/playback/gststreaminfo.h

index d76f850de1ecf4e176dcfc41bcf9ae08dd4f94d0..2ae5e7d318baa1998a3f2b7944e1a402cd4adee7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2004-10-18  Wim Taymans  <wim@fluendo.com>
+
+       * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init),
+       (gst_decode_bin_init), (find_compatibles), (close_pad_link),
+       (try_to_link_1), (no_more_pads), (close_link), (type_found):
+       * gst/playback/gstplaybasebin.c: (gen_preroll_element),
+       (remove_prerolls), (unknown_type), (add_element_stream),
+       (new_decoded_pad), (setup_source), (gst_play_base_bin_add_element),
+       (gst_play_base_bin_remove_element),
+       (gst_play_base_bin_link_stream):
+       * gst/playback/gstplaybin.c: (gen_video_element),
+       (gen_vis_element), (remove_sinks), (setup_sinks):
+       * gst/playback/gststreaminfo.c: (gst_stream_type_get_type),
+       (gst_stream_info_get_type), (gst_stream_info_class_init),
+       (gst_stream_info_init), (gst_stream_info_new),
+       (gst_stream_info_dispose), (stream_info_mute_pad),
+       (gst_stream_info_set_property), (gst_stream_info_get_property):
+       * gst/playback/gststreaminfo.h:
+       Add sink padtemplate to decodebin.
+       Added some more comments.
+       Make queue size configurable in playbasebin.
+       Added possibility to use elements as sinks (ex cdaudio).
+
 2004-10-15  Wim Taymans  <wim@fluendo.com>
 
        * ext/speex/gstspeexenc.c: (gst_speexenc_class_init),
index fad169d439b83c74bcd35ab206be4e57d43be562..d7920f1e91f0e0218a9e0c9c6fff8d7582587a8b 100644 (file)
@@ -40,6 +40,7 @@ playbin:
    stream detected. implements seeking and querying on the configured sinks.
 
    TODO
+   - visualisation
    - reuse, refcounting, cleanup in READY state
    - debugging
    - error handling
index 8da8a1257e64d57a97d6d1cd6d0bab6bf54945c2..cad836cee2862ab2fa5da70fcc29dd5f8ffca349 100644 (file)
 #include <gst/gst.h>
 
 /* generic templates */
-GstStaticPadTemplate decoder_bin_sink_template =
+static GstStaticPadTemplate decoder_bin_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS_ANY);
 
-GstStaticPadTemplate decoder_bin_src_template =
+static GstStaticPadTemplate decoder_bin_src_template =
 GST_STATIC_PAD_TEMPLATE ("src%d",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
@@ -192,6 +192,8 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
 
   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
 
+  gst_element_class_add_pad_template (gstelement_klass,
+      gst_static_pad_template_get (&decoder_bin_sink_template));
   gst_element_class_add_pad_template (gstelement_klass,
       gst_static_pad_template_get (&decoder_bin_src_template));
 
index 735207a4ccecead0ae00611ff98cdfe4f86e077e..e72de9d9812f6c9c33a21f69c678079bdf017812 100644 (file)
@@ -206,6 +206,11 @@ queue_overrun (GstElement * element, GstPlayBaseBin * play_base_bin)
   g_mutex_unlock (play_base_bin->preroll_lock);
 }
 
+/* generate a preroll element which is simply a queue. While there
+ * are still dynamic elements in the pipeline, we wait for one
+ * of the queues to fill. The assumption is that all the dynamic
+ * streams will be detected by that time. 
+ */
 static GstElement *
 gen_preroll_element (GstPlayBaseBin * play_base_bin, GstPad * pad)
 {
@@ -217,9 +222,13 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, GstPad * pad)
   element = gst_element_factory_make ("queue", name);
   g_object_set (G_OBJECT (element), "max-size-buffers", 0, NULL);
   g_object_set (G_OBJECT (element), "max-size-bytes", 0, NULL);
-  g_object_set (G_OBJECT (element), "max-size-time", 3 * GST_SECOND, NULL);
-  sig = g_signal_connect (G_OBJECT (element), "overrun",
+  g_object_set (G_OBJECT (element), "max-size-time", play_base_bin->queue_size,
+      NULL);
+  sig =
+      g_signal_connect (G_OBJECT (element), "overrun",
       G_CALLBACK (queue_overrun), play_base_bin);
+  /* keep a ref to the signal id so that we can disconnect the signal callback
+   * when we are done with the preroll */
   g_object_set_data (G_OBJECT (element), "signal_id", GINT_TO_POINTER (sig));
   g_free (name);
 
@@ -231,6 +240,7 @@ remove_prerolls (GstPlayBaseBin * play_base_bin)
 {
   GList *prerolls, *infos;
 
+  /* remove the preroll queues */
   for (prerolls = play_base_bin->preroll_elems; prerolls;
       prerolls = g_list_next (prerolls)) {
     GstElement *element = GST_ELEMENT (prerolls->data);
@@ -241,6 +251,7 @@ remove_prerolls (GstPlayBaseBin * play_base_bin)
   g_list_free (play_base_bin->preroll_elems);
   play_base_bin->preroll_elems = NULL;
 
+  /* free the streaminfo too */
   for (infos = play_base_bin->streaminfo; infos; infos = g_list_next (infos)) {
     GstStreamInfo *info = GST_STREAM_INFO (infos->data);
 
@@ -254,6 +265,9 @@ remove_prerolls (GstPlayBaseBin * play_base_bin)
   play_base_bin->nunknownpads = 0;
 }
 
+/* signal fired when an unknown stream is found. We create a new
+ * UNKNOWN streaminfo object 
+ */
 static void
 unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
     GstPlayBaseBin * play_base_bin)
@@ -265,12 +279,31 @@ unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
   g_warning ("don't know how to handle %s", capsstr);
 
   /* add the stream to the list */
-  info = gst_stream_info_new (pad, GST_STREAM_TYPE_UNKNOWN, NULL);
+  info = gst_stream_info_new (GST_OBJECT (pad), GST_STREAM_TYPE_UNKNOWN, NULL);
   play_base_bin->streaminfo = g_list_append (play_base_bin->streaminfo, info);
 
   g_free (capsstr);
 }
 
+/* add a streaminfo that indicates that the stream is handled by the
+ * given element. This usually means that a stream without actual data is
+ * produced but one that is sunken by an element. Examples of this are:
+ * cdaudio, a hardware decoder/sink, dvd meta bins etc...
+ */
+static void
+add_element_stream (GstElement * element, GstPlayBaseBin * play_base_bin)
+{
+  GstStreamInfo *info;
+
+  /* add the stream to the list */
+  info =
+      gst_stream_info_new (GST_OBJECT (element), GST_STREAM_TYPE_ELEMENT, NULL);
+  play_base_bin->streaminfo = g_list_append (play_base_bin->streaminfo, info);
+}
+
+/* when the decoder element signals that no more pads will be generated, we
+ * can stop the preroll
+ */
 static void
 no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin)
 {
@@ -282,6 +315,9 @@ no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin)
   g_mutex_unlock (play_base_bin->preroll_lock);
 }
 
+/* signal fired when decodebin has found a new raw pad. We create
+ * a preroll element if needed and the appropriate streaminfo.
+ */
 static void
 new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
     GstPlayBaseBin * play_base_bin)
@@ -297,13 +333,14 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
 
   GST_DEBUG ("play base: new decoded pad %d", last);
 
+  /* first see if this pad has interesting caps */
   caps = gst_pad_get_caps (pad);
-
-  if (gst_caps_is_empty (caps)) {
+  if (caps == NULL || gst_caps_is_empty (caps)) {
     g_warning ("no type on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
     return;
   }
 
+  /* get the mime type */
   structure = gst_caps_get_structure (caps, 0);
   mimetype = gst_structure_get_name (structure);
 
@@ -352,7 +389,7 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
   }
 
   /* add the stream to the list */
-  info = gst_stream_info_new (srcpad, type, NULL);
+  info = gst_stream_info_new (GST_OBJECT (srcpad), type, NULL);
   play_base_bin->streaminfo = g_list_append (play_base_bin->streaminfo, info);
 
   /* signal the no more pads after adding the stream */
@@ -360,6 +397,10 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
     no_more_pads (NULL, play_base_bin);
 }
 
+/* signal fired when the internal thread performed an unexpected  
+ * state change. This usually indicated an error occured. We stop the
+ * preroll stage.
+ */
 static void
 state_change (GstElement * element,
     GstElementState old_state, GstElementState new_state, gpointer data)
@@ -377,6 +418,9 @@ state_change (GstElement * element,
   }
 }
 
+/* construct and run the source and decoder elements until we found
+ * all the streams or until a preroll queue has been filled.
+ */
 static gboolean
 setup_source (GstPlayBaseBin * play_base_bin)
 {
@@ -387,14 +431,15 @@ setup_source (GstPlayBaseBin * play_base_bin)
   if (!play_base_bin->need_rebuild)
     return TRUE;
 
+  /* keep ref to old souce in case creating the new source fails */
   old_src = play_base_bin->source;
 
-  /* create and configure an element that can handle the uri 
-   */
+  /* create and configure an element that can handle the uri */
   play_base_bin->source =
       gst_element_make_from_uri (GST_URI_SRC, play_base_bin->uri, "source");
 
   if (!play_base_bin->source) {
+    /* whoops, could not create the source element */
     g_warning ("don't know how to read %s", play_base_bin->uri);
     play_base_bin->source = old_src;
     return FALSE;
@@ -404,27 +449,35 @@ setup_source (GstPlayBaseBin * play_base_bin)
       gst_bin_remove (GST_BIN (play_base_bin->thread), old_src);
     }
     gst_bin_add (GST_BIN (play_base_bin->thread), play_base_bin->source);
+    /* make sure the new element has the same state as the parent */
     if (gst_bin_sync_children_state (GST_BIN (play_base_bin->thread)) ==
         GST_STATE_FAILURE) {
       return FALSE;
     }
   }
 
+  /* remove the old decoder now, if any */
   old_dec = play_base_bin->decoder;
   if (old_dec) {
     GST_LOG ("removing old decoder element %s", gst_element_get_name (old_dec));
     gst_bin_remove (GST_BIN (play_base_bin->thread), old_dec);
   }
 
+  /* remove our previous preroll queues */
   remove_prerolls (play_base_bin);
 
   /* now see if the source element emits raw audio/video all by itself,
-   * if so, we can create streams for the pads and be done with it 
+   * if so, we can create streams for the pads and be done with it.
+   * Also check that is has source pads, if now, we assume it will
+   * do everything itself.
    */
   {
     const GList *pads;
     gboolean is_raw = FALSE;
 
+    /* assume we are going to have no output streams */
+    gboolean no_out = TRUE;
+
     for (pads = gst_element_get_pad_list (play_base_bin->source);
         pads; pads = g_list_next (pads)) {
       GstPad *pad = GST_PAD (pads->data);
@@ -435,6 +488,8 @@ setup_source (GstPlayBaseBin * play_base_bin)
       if (GST_PAD_IS_SINK (pad))
         continue;
 
+      no_out = FALSE;
+
       srcpad = pad;
       caps = gst_pad_get_caps (pad);
 
@@ -449,28 +504,25 @@ setup_source (GstPlayBaseBin * play_base_bin)
           g_str_has_prefix (mimetype, "video/x-raw")) {
         new_decoded_pad (play_base_bin->source, pad, g_list_next (pads) == NULL,
             play_base_bin);
-
         is_raw = TRUE;
       }
     }
     if (is_raw) {
       return TRUE;
     }
-  }
-
-  if (srcpad == NULL) {
-    /* FIXME we do not handle this yet, but we should just make sure that
-     * we don't error on this because there is no streaminfo. A possible element
-     * without any source pads could be cdaudio, which just plays an audio cd 
-     */
-    GST_DEBUG_OBJECT (play_base_bin, "have source element without source pad");
-    return FALSE;
+    if (no_out) {
+      /* create a stream to indicate that this uri is handled by a self
+       * contained element */
+      add_element_stream (play_base_bin->source, play_base_bin);
+      return TRUE;
+    }
   }
 
   {
     gboolean res;
     gint sig1, sig2, sig3, sig4;
 
+    /* now create the decoder element */
     play_base_bin->decoder = gst_element_factory_make ("decodebin", "decoder");
     if (!play_base_bin->decoder) {
       g_warning ("can't find decoder element");
@@ -710,6 +762,9 @@ gst_play_base_bin_change_state (GstElement * element)
   return ret;
 }
 
+/* virtual function to add elements to this bin. The idea is to
+ * wrap the element in a thread automatically.
+ */
 static void
 gst_play_base_bin_add_element (GstBin * bin, GstElement * element)
 {
@@ -734,7 +789,7 @@ gst_play_base_bin_add_element (GstBin * bin, GstElement * element)
     }
     gst_bin_add (GST_BIN (play_base_bin->thread), element);
 
-    /* hack */
+    /* hack, the clock is not correctly distributed in the core */
     sched = gst_element_get_scheduler (GST_ELEMENT (play_base_bin->thread));
     clock = gst_scheduler_get_clock (sched);
     gst_scheduler_set_clock (sched, clock);
@@ -748,6 +803,10 @@ gst_play_base_bin_add_element (GstBin * bin, GstElement * element)
   }
 }
 
+/* virtual function to remove an element from this bin. We have to make
+ * sure that we also remove the thread that we used as a container for
+ * this element.
+ */
 static void
 gst_play_base_bin_remove_element (GstBin * bin, GstElement * element)
 {
@@ -767,14 +826,18 @@ gst_play_base_bin_remove_element (GstBin * bin, GstElement * element)
       if (!thread) {
         g_warning ("cannot find element to remove");
       } else {
-        /* we remove the element from the thread first so that the
-         * state is not affected when someone holds a reference to it */
-        gst_bin_remove (GST_BIN (thread), element);
+        if (gst_element_get_parent (element) == GST_OBJECT (thread)) {
+          /* we remove the element from the thread first so that the
+           * state is not affected when someone holds a reference to it */
+          gst_bin_remove (GST_BIN (thread), element);
+        }
         element = thread;
       }
     }
-    GST_LOG ("removing element %s", gst_element_get_name (element));
-    gst_bin_remove (GST_BIN (play_base_bin->thread), element);
+    if (gst_element_get_parent (element) == GST_OBJECT (play_base_bin->thread)) {
+      GST_LOG ("removing element %s", gst_element_get_name (element));
+      gst_bin_remove (GST_BIN (play_base_bin->thread), element);
+    }
   } else {
     g_warning ("removing elements is not allowed in NULL");
   }
@@ -839,17 +902,20 @@ gst_play_base_bin_link_stream (GstPlayBaseBin * play_base_bin,
         streams = g_list_next (streams)) {
       GstStreamInfo *sinfo = (GstStreamInfo *) streams->data;
 
-      if (gst_pad_is_linked (sinfo->pad))
+      if (sinfo->type == GST_STREAM_TYPE_ELEMENT)
+        continue;
+
+      if (gst_pad_is_linked (GST_PAD (sinfo->object)))
         continue;
 
-      if (gst_pad_can_link (sinfo->pad, pad)) {
+      if (gst_pad_can_link (GST_PAD (sinfo->object), pad)) {
         info = sinfo;
         break;
       }
     }
   }
   if (info) {
-    if (!gst_pad_link (info->pad, pad)) {
+    if (!gst_pad_link (GST_PAD (info->object), pad)) {
       GST_DEBUG ("could not link");
       g_object_set (G_OBJECT (info), "mute", TRUE, NULL);
     }
index f432c453d0eac4d8d477ff7baab9fe4516de8cf3..3feb14243cbf96ffbb36570d2e4e68b80ca430a1 100644 (file)
@@ -111,7 +111,7 @@ static GstElementDetails gst_play_bin_details = {
   "Player Bin",
   "Generic/Bin/Player",
   "Autoplug and play media from an uri",
-  "Wim Taymans <wim.taymans@chello.be>"
+  "Wim Taymans <wim@fluendo.com>"
 };
 
 
@@ -306,6 +306,9 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
   }
 }
 
+/* signal fired when the identity has received a new buffer. This is used for
+ * making screenshots.
+ */
 static void
 handoff (GstElement * identity, GstBuffer * frame, gpointer data)
 {
@@ -317,6 +320,9 @@ handoff (GstElement * identity, GstBuffer * frame, gpointer data)
   play_bin->frame = gst_buffer_ref (frame);
 }
 
+/* make the element (bin) that contains the elements needed to perform
+ * video display/
+ */
 static GstElement *
 gen_video_element (GstPlayBin * play_bin)
 {
@@ -326,9 +332,12 @@ gen_video_element (GstPlayBin * play_bin)
   GstElement *sink;
   GstElement *identity;
 
+  /* first see if we have it in the cache */
   element = g_hash_table_lookup (play_bin->cache, "vbin");
   if (element != NULL) {
     g_object_ref (G_OBJECT (element));
+    /* need to get the video sink element as we need to add it to the
+     * list of seekable elements */
     sink = g_hash_table_lookup (play_bin->cache, "video_sink");
     goto done;
   }
@@ -492,6 +501,9 @@ remove_sinks (GstPlayBin * play_bin)
   if (element != NULL) {
     parent = gst_element_get_parent (element);
     if (parent != NULL) {
+      /* we remove the element from the parent so that
+       * there is no unwanted state change when the parent
+       * is disposed */
       gst_bin_remove (GST_BIN (parent), element);
     }
   }
@@ -520,6 +532,9 @@ remove_sinks (GstPlayBin * play_bin)
   }
 }
 
+/* loop over the streams and set up the pipeline to play this
+ * media file
+ */
 static void
 setup_sinks (GstPlayBin * play_bin)
 {
@@ -539,8 +554,14 @@ setup_sinks (GstPlayBin * play_bin)
     GstPad *srcpad;
 
     g_object_get (obj, "type", &type, NULL);
-    g_object_get (obj, "pad", &srcpad, NULL);
+    /* we don't care about streams with their own sink */
+    if (type == 4)
+      continue;
+
+    /* else we need to get the pad */
+    g_object_get (obj, "object", &srcpad, NULL);
 
+    /* hmm.. pad is allready linked */
     if (gst_pad_is_linked (srcpad))
       continue;
 
@@ -558,6 +579,7 @@ setup_sinks (GstPlayBin * play_bin)
   num_audio = 0;
   num_video = 0;
 
+  /* now actually connect everything */
   for (s = streaminfo; s; s = g_list_next (s)) {
     GObject *obj = G_OBJECT (s->data);
     gint type;
@@ -565,9 +587,18 @@ setup_sinks (GstPlayBin * play_bin)
     GstElement *sink = NULL;
     gboolean res;
     gboolean mute = FALSE;
+    GstObject *object;
 
     g_object_get (obj, "type", &type, NULL);
-    g_object_get (obj, "pad", &srcpad, NULL);
+    g_object_get (obj, "object", &object, NULL);
+
+    /* use the sink elements as seek entry point */
+    if (type == 4) {
+      play_bin->seekables = g_list_prepend (play_bin->seekables, object);
+      continue;
+    }
+
+    srcpad = GST_PAD (object);
 
     if (gst_pad_is_linked (srcpad))
       continue;
@@ -592,6 +623,8 @@ setup_sinks (GstPlayBin * play_bin)
         sink = gen_video_element (play_bin);
         num_video++;
       }
+    } else if (type == 4) {
+      /* we can ignore these streams here */
     } else {
       g_warning ("unknown stream found");
       mute = TRUE;
index d38a76f9b5257f61e9b361f9a6766d3026ca028b..e1fd17247c5c3e9065e8e3bd222c32094b676d92 100644 (file)
@@ -53,6 +53,9 @@ gst_stream_type_get_type (void)
     {GST_STREAM_TYPE_UNKNOWN, "GST_STREAM_TYPE_UNKNOWN", "Unknown stream"},
     {GST_STREAM_TYPE_AUDIO, "GST_STREAM_TYPE_AUDIO", "Audio stream"},
     {GST_STREAM_TYPE_VIDEO, "GST_STREAM_TYPE_VIDEO", "Video stream"},
+    {GST_STREAM_TYPE_TEXT, "GST_STREAM_TYPE_TEXT", "Text stream"},
+    {GST_STREAM_TYPE_ELEMENT, "GST_STREAM_TYPE_ELEMENT",
+          "Stream handled by element"},
     {0, NULL, NULL},
   };
 
@@ -113,8 +116,9 @@ gst_stream_info_class_init (GstStreamInfoClass * klass)
   gobject_klass->get_property = gst_stream_info_get_property;
 
   g_object_class_install_property (gobject_klass, ARG_PAD,
-      g_param_spec_object ("pad", "Pad", "Source Pad of the stream",
-          GST_TYPE_PAD, G_PARAM_READABLE));
+      g_param_spec_object ("object", "object",
+          "Source Pad or object of the stream", GST_TYPE_OBJECT,
+          G_PARAM_READABLE));
   g_object_class_install_property (gobject_klass, ARG_TYPE,
       g_param_spec_enum ("type", "Type", "Type of the stream",
           GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN, G_PARAM_READABLE));
@@ -137,21 +141,21 @@ gst_stream_info_class_init (GstStreamInfoClass * klass)
 static void
 gst_stream_info_init (GstStreamInfo * stream_info)
 {
-  stream_info->pad = NULL;
+  stream_info->object = NULL;
   stream_info->type = GST_STREAM_TYPE_UNKNOWN;
   stream_info->decoder = NULL;
   stream_info->mute = FALSE;
 }
 
 GstStreamInfo *
-gst_stream_info_new (GstPad * pad, GstStreamType type, gchar * decoder)
+gst_stream_info_new (GstObject * object, GstStreamType type, gchar * decoder)
 {
   GstStreamInfo *info;
 
   info = g_object_new (GST_TYPE_STREAM_INFO, NULL);
 
-  gst_object_ref (GST_OBJECT (pad));
-  info->pad = pad;
+  gst_object_ref (object);
+  info->object = object;
   info->type = type;
   info->decoder = g_strdup (decoder);
 
@@ -165,8 +169,8 @@ gst_stream_info_dispose (GObject * object)
 
   stream_info = GST_STREAM_INFO (object);
 
-  gst_object_unref (GST_OBJECT (stream_info->pad));
-  stream_info->pad = NULL;
+  gst_object_unref (stream_info->object);
+  stream_info->object = NULL;
   stream_info->type = GST_STREAM_TYPE_UNKNOWN;
   g_free (stream_info->decoder);
 
@@ -222,11 +226,16 @@ gst_stream_info_set_property (GObject * object, guint prop_id,
   switch (prop_id) {
     case ARG_MUTE:
     {
+      if (stream_info->type == GST_STREAM_TYPE_ELEMENT) {
+        g_warning ("cannot mute element stream");
+        break;
+      }
       gboolean new_mute = g_value_get_boolean (value);
 
       if (new_mute != stream_info->mute) {
         stream_info->mute = new_mute;
-        stream_info_mute_pad (stream_info, stream_info->pad, new_mute);
+        stream_info_mute_pad (stream_info, GST_PAD (stream_info->object),
+            new_mute);
       }
       break;
     }
@@ -248,7 +257,7 @@ gst_stream_info_get_property (GObject * object, guint prop_id, GValue * value,
 
   switch (prop_id) {
     case ARG_PAD:
-      g_value_set_object (value, stream_info->pad);
+      g_value_set_object (value, stream_info->object);
       break;
     case ARG_TYPE:
       g_value_set_enum (value, stream_info->type);
index 22d34dd0e33b20f2508886c9e431ca624cb6462b..e1504b1eb897a91431ba22c4a18254a25bca67ba 100644 (file)
@@ -39,12 +39,13 @@ typedef enum {
   GST_STREAM_TYPE_AUDIO   = 1,
   GST_STREAM_TYPE_VIDEO   = 2,
   GST_STREAM_TYPE_TEXT    = 3,
+  GST_STREAM_TYPE_ELEMENT = 4,
 } GstStreamType;
 
 struct _GstStreamInfo {
   GObject       parent;
 
-  GstPad       *pad;
+  GstObject    *object;
   GstStreamType         type;
   gchar        *decoder;
   gboolean      mute;
@@ -59,7 +60,7 @@ struct _GstStreamInfoClass {
 
 GType gst_stream_info_get_type (void);
 
-GstStreamInfo* gst_stream_info_new (GstPad *pad, GstStreamType type, gchar *decoder);
+GstStreamInfo* gst_stream_info_new (GstObject *object, GstStreamType type, gchar *decoder);
 
 G_END_DECLS